Paulund

Building A Weather App With VueJS

In this tutorial we're going to build a component we can use to display the weather of a location in VueJS. This component will be created with a location search textbox, this will then search a free weather API to get the information for the location based search. First lets create the HTML with the weather component, then the JavaScript files of Vue and Vue-resource. Vue-resource is the Vue library used to make HTTP requests. The final JavaScript file is the app.js which is what we'll use for the weather component.

<div id="app">
    <h1>VueJS: Weather</h1>

    <weather></weather>

</div>

<script src='https://unpkg.com/vue@next/dist/vue.js'></script>
<script src="https://unpkg.com/[email protected]/dist/vue-resource.min.js"></script>
<script src="js/app.js"></script>

The first thing we need to do is build the Vue object that will mount to the #app div.


var app = new Vue({
    el: '#app',
    data: {
    }
});

The first component we're going to make is the main weather component, this will need 3 properties attached to it, data, methods and template. The data array will need the data points of: - Location - Data link to the textbox

  • ApiKey - Your open weather api key http://openweathermap.org/appid
  • Weather - Store the results of the api
  • DisplayWeather - Boolean to display the weather section

The method we need to create is the API call to the openweather API, to make this call we're going to use Vue Resource method for .get(). The results of this method will be stored in the weather data point and then set the displayWeather data point to true. The template we're going to create is going to start with a form for the user to enter their location. On the submit event of the form we're going to call the getWeather method. On the textbox we need to link it to the data property using the directive v-model. Then we can populate the template with the components of the different weather data. - coord - Display the coordinates

  • weather-display - Display the weather information
  • temperature - Display the temperature stats
  • winds - Display the winds stats
  • clouds - Show the stats for the cloud information
  • sun - Display information about sunrise and sunset

On each of these components we use the v-bind directive to pass in data by using a prop.

Vue.component('weather', {

    data: function(){
        return {
            location: '',
            apiKey: {INSERT_API_KEY},
            weather: [],
            displayWeather: false
        }
    },

    methods: {
        getWeather: function()
        {
            return this.$http.get('http://api.openweathermap.org/data/2.5/weather?q='+ this.location +'&appid=' + this.apiKey).then((response) => {
                this.weather = response.body;
                this.displayWeather = true
            }, (response) => {
                this.weather = [];
                this.displayWeather = false
            });
        }
    },

    template: '<div id="weatherApp"><form v-on:submit.prevent="getWeather"><p><input type="text" name="location" v-model="location"></p><p>' +
                '<button class="btn btn-primary">Search</button>' +
                '</p>' +
            '</form>' +
            '<div v-if="displayWeather" class="container display-weather-section"><h1>{{ weather.name }}</h1>' +
            '<coord v-bind:coord="weather.coord"></coord>' +
            '<weather-display v-bind:weatherDisplay="weather.weather[0]"></weather-display>' +
            '<temperature v-bind:temperature="weather.main"></temperature>' +
            '<winds v-bind:wind="weather.wind"></winds>' +
            '<clouds v-bind:cloud="weather.clouds"></clouds>' +
            '<sun v-bind:sun="weather.sys"></sun>' +
            '</div></div>'
});

The coordinates component will receive data from a coord prop and display these in the template.


Vue.component('coord', {
    props: ['coord'],

    template: '<div id="coord" class="col-xs-4">' +
                '<h2>Coordinates</h2>' +
                '<p><strong>Lng</strong> {{ coord.lon }}</p>' +
                '<p><strong>Lat</strong> {{ coord.lat }}</p></div>'
});

The weather display component will receive data from a weatherDisplay prop and display the name and description of the weather.


Vue.component('weather-display', {
    props: ['weatherDisplay'],

    template: '<div id="weatherDisplay" class="col-xs-4">' +
                '<h2>{{ weatherDisplay.main }}</h2>' +
                '<p>{{ weatherDisplay.description }}</p>' +
                '</div>'
});

The temperature component will take a prop of temperature, then the template will display the avg temp, max temp and min temp. The data we get from open weather api is in the format of kelvin, so we need to create a function to convert the temperature. To convert kelvin to celsius you simply need to subtract 273.15 from the number.


Vue.component('temperature', {
    props: ['temperature'],

    methods: {
        displayTemp: function( temp )
        {
            return parseFloat(temp - 273.15).toFixed(2);
        }
    },

    template: '<div id="temp" class="col-xs-4">' +
                '<h2>Temperature</h2>' +
                '<p>Avg Temp - {{ displayTemp(temperature.temp) }}c</p>' +
                '<p>Min Temp - {{ displayTemp(temperature.temp_min) }}c</p>' +
                '<p>Max Temp - {{ displayTemp(temperature.temp_max) }}c</p>' +
                '</div>'
});

The winds component will display both the speed and the direction of the wind, this is received from a wind prop. The wind direction data is returned in the format of degrees. We then need to create a method that will convert these degrees to a compass label. Then we can display the template which will output the speed and the return of the degreesToCompass method.


Vue.component('winds', {
    props: ['wind'],

    methods: {
        degreesToCompass: function(deg)
        {
            var val = Math.floor((deg / 22.5) + 0.5);
            var dir = ["N","NNE","NE","ENE","E","ESE", "SE", "SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"];

            return dir[(val % 16)];
        }
    },

    template: '<div id="wind" class="col-xs-4">' +
                '<h2>Wind</h2>' +
                '<p>Speed - {{ wind.speed }}</p>' +
                '<p>Direction - {{ degreesToCompass(wind.deg) }}</p>' +
                '</div>'
});

The cloud component will take a prop of cloud and will display the cloud coverage for the location.


Vue.component('clouds', {
    props: ['cloud'],

    template: '<div id="cloud" class="col-xs-4">' +
                '<h2>Clouds</h2>' +
                '<p>Coverage - {{ cloud.all }}%</p>' +
                '</div>'
});

The sun component will display the sunrise and sunset times, we need to create a method to convert the timestamp to a date time format.


Vue.component('sun', {
    props: ['sun'],

    methods: {
        timestampToDate: function( timestamp ){
            var date = new Date(timestamp*1000);
            return date.toString();
        }
    },

    template: '<div id="sun" class="col-xs-4">' +
                '<h2>Sun</h2>' +
                '<p>Sunrise - {{ timestampToDate(sun.sunrise) }}</p>' +
                '<p>Sunset - {{ timestampToDate(sun.sunset) }}</p>' +
            '</div>'
});

That's all the components you need to create a weather application, now you can view the demo to see how it works.