Building A Weather App Using Vue.js From Scratch

Niraj Thing
6 min readDec 16, 2020

Today, Vue.js ranks among one of the most popular framework since its launch in 2014. It is the newest and youngest member among the other two most popular frameworks Angular and React. Some of the popular websites built using Vue.js are Gitlab, Behance, Nientendo, Laravel, Font Awesome etc.

Photo by : Florian Olivo on unsplash.com

First Step:

Before we build our application make sure you have node, Vue.js and Vue CLI installed on your computer.

Creating our application:

Once you have installed the above requirements, we can create our weather app by entering the following command on our terminal.

vue create weather-app                          

After that, it will provide you an option to choose different version of Vue.js with default preset or you can also manually select multiple features. Here, we will select Vue 2 of default preset with babel and eslint.

Once the packages are installed, we can now go to our file location by entering following command.

cd weather-app

Starting our development server:

We will simply start our development server through the following command in the terminal. By default, our server runs on http://localhost:8080/. But if you already have server running at 8080 then it will run at 8081 and so on.

npm run serve

Now, if we open our browser and go to our development server address, we will see a default home page of Vue like this.

File Structure:

Right now, our file structure will look like this but we have to make changes in HelloWorld.vue and App.vue components.

> node_modules
> public
> src
> assets
logo.png
> components
HelloWorld.vue
App.vue
main.js
.gitignore
babel.config.js
package-lock.json
package.json
README.md

Changes to HelloWorld.vue component:

Let’s go to our HelloWorld.vue component and remove everything inside template, script and style tags. Also, change the component name to weather-app.vue.

Our component should look like this.

<template></template><script></script><style> <style>

Changes to App.vue component:

Now, let’s make some changes to our main component which is App.vue. Now inside our template tag, remove the default <img> and<Helloworld> tags.

Inside our script tag we have by default HelloWorld.vue imported from our components folder. Let’s quickly remove that component and import our weather-app.vue as we have already changed the name of our component from HelloWorld.vue.

We have to change the name of the component to weather-app.vue inside our export default syntax as well. Export default is a syntax from ES modules which provides us a way to export the components from their respective modules and use it in other files. Then include the component in template tag. Let’s remove the css from our style tag too.

Our App.vue should look like this.

<template>  <div id="app">    <weatherApp/>  </div></template><script>import weatherApp from './components/weather-app.vue'export default { name: 'App', components: {  weatherApp }}</script><style></style>

Our weather-app.vue component:

Inside our weather-app.vue component, let’s first write html code inside our template tag.

<template> <div class="weather-container">  <div class="weather-wrap">   <div class="search-box">    <input type="text" placeholder="Search..." class="search-bar" 
v-model="query" v-on:keypress="fetchWeather" />
</div> <div class="weather-info" v-if="typeof weather.main!=undefined'"> <div class="location-box"> <div class="location">{{weather.name}},{{weather.sys.country }} </div> <div class="date">{{ todaysDate() }}</div> </div> <div class="weather-box"> <div class="temp">{{ Math.round(weather.main.temp) }}°c</div> <div class="weather">{{ weather.weather[0].main }}</div> <div class="icon">
<img:src="`${weather_icon}${weather.weather[0].icon}${'@2x.png'}`"/>
</div> </div> </div> </div></div></template>

This is what our html code should look like. Now, let’s do some css magic and make the app look stunning. For the font, we will import ‘Montserrat’ from google fonts.

<style>@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@300;500;700;900&display=swap");* {margin: 0;padding: 0;box-sizing: border-box;font-family: "Montserrat";}.weather-container{background-image: url("../assets/default.jpg");background-size: cover;background-position: center;transition: 0.4s;width: 375px;margin: 0 auto;border-radius: 25px;margin-top: 50px;box-shadow: 0px 0px 30px #00000065;}.weather-wrap {height: 600px;padding: 25px;border-radius: 25px;background-image: linear-gradient(to bottom,rgba(0, 0, 0, 0.15),rgba(0, 0, 0, 0.4));}.search-box .search-bar {display: block;width: 100%;padding: 15px;color: #313131;font-size: 20px;appearance: none;border: none;outline: none;background: none;background-color: rgba(255, 255, 255, 0.5);box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.25);border-radius: 10px;transition: 0.4s;}.search-box .search-bar:focus {box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.25);background-color: rgba(255, 255, 255, 0.75);}.location-box .location {color: #fff;font-size: 32px;font-weight: 500;font-style: italic;text-align: center;margin-top: 30px;}.location-box .date {color: #fff;font-size: 20px;font-weight: 300;text-align: center;}.weather-box {text-align: center;}.weather-box .temp {display: inline-block;padding: 10px 25px;color: #fff;font-size: 102px;font-weight: 900;text-shadow: 3px 6px rgba(0, 0, 0, 0.25);background-color: rgba(255, 255, 255, 0.25);border-radius: 16px;margin: 30px 0px;box-shadow: 3px 6px rgba(0, 0, 0, 0.25);font-style: italic;}.weather-box .weather {color: #fff;font-size: 48px;font-weight: 700;font-style: italic;text-shadow: 3px 6px rgba(0, 0, 0, 0.25);}
</style>

Now inside our script tag, we will use axios to retrieve data from api. There is an inbuilt JavaScript method called Fetch() as well. There are some differences between axios and fetch(). I will try to explain the difference between two of them in my next blog.

To use axios we first need to install it. Enter the following command inside the terminal to install.

npm i axios

Next step is to import the axios and return some parameters in our data method inside export default syntax. To get the api key you should sign up on open weather app.

import axios from "axios";export default { data() {  return {   api_key: "27bcc252742830381afd6856832da01a",   url_base: "https://api.openweathermap.org/data/2.5/",   weather_icon: "http://openweathermap.org/img/wn/",   query: "",   weather: {},  };
},
};

Now we have the api, we need to run a function when we search inside our input field. We will use v-model directive inside our input field which create two-way data bindings. It create two-way data bindings between user input and vue.js component which means whenever the model changes it updates the template. Now we will pass query property inside the v-model which currently is empty.

<input type="text" placeholder="Search..." class="search-bar" 
v-model="query" v-on:keypress="fetchWeather" />

After that, we will perform a function called fetchWeather whenever a key is pressed inside the input form. For that, we will use v-on: directive to listen to DOM events whenever they are triggered. In this case whenever a key is pressed fetchWeather function will be triggered. But we don’t want that to happen because we only want the function to run when we press the enter key. So we will use an if condition for that.

async fetchWeather(e) { if (e.key == "Enter") {  let response = await axios.get(`${this.url_base}weather? q=${this.query}&units=metric&APPID=${this.api_key}`); this.setResults(response.data); }
},
setResults(returnedResponse) {
this.weather = returnedResponse;
},

Here, when our function is triggered an event object is passed as a parameter which represents an event that caused the function to be triggered. So when the key event is “Enter”, then only it executes the function.

Then we retrieve the data from api and put it inside response variable. And every time a search is made we need another function called setResults() to be called which will set data that we retrieve from an api. We will pass the response data as an argument.

For date we will use a function called todaysDate() which will return us month, date, day and year respectively. Our whole code looks like this.

import axios from "axios";export default {data() {return {api_key: "27bcc252742830381afd6856832da01a",url_base: "https://api.openweathermap.org/data/2.5/",weather_icon: "http://openweathermap.org/img/wn/",query: "",weather: {},};},methods: {async fetchWeather(e) {if (e.key == "Enter") {let response = await axios.get(`${this.url_base}weather?q=${this.query}&units=metric&APPID=${this.api_key}`);this.setResults(response.data);}},setResults(returnedResponse) {this.weather = returnedResponse;},todaysDate() {const months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",];const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];let d = new Date();let month = months[d.getMonth()];let day = days[d.getDay()];let date = d.getDate();let year = d.getFullYear();return `${month} ${date} ${day} ${year}`;},},};</script>

Conclusion:

In this article, we first learned how to create a vue application and gradually build the whole app thoroughly. Now as we search through different location in the input field, it will provide us the data through the api and display the data inside their respective div, Hence the speed, lightweight and easier learning curve makes vue.js one of the growing sensation among web development community.

If you have any questions, you can contact me through LinkedIn.

--

--