Vue js JSON tutorial

Vue.js: Get and Display JSON Data with Fetch and Axios

Vue js JSON tutorial

In this tutorial we will:

  • Create a simple weather app by fetching data from a local JSON file using the fetch API.
  • We will create the app from scratch using Vue CLI.
  • Use CSS with flexbox to make the design look good.
  • Replace the fetch API with axios

This is what the final result will look like:

My Weather app result

#1 Create the Project with the Vue CLI

In other to use the Vue CLI, you need to download and install Node.js. Install the CLI by typing the following in a terminal.

npm install -g @vue/cli

After the CLI is installed, create the Vue app by using the create command.

vue create weather-json

You will then have the option to select a preset. We will only select the default for now.

#2 Run the Vue CLI Starter App in the Browser

Now we have created a basic Vue CLI project called weather-json. Go into the folder by typing this in the command:

cd weather-json

Use the npm run serve command to start a local web server.

npm run serve
npm run serve terminal output

As you can see in the terminal, the CLI has started up a local server on “http://localhost:8080”. Open a new tab on your browser and enter this URL.

You should see something like this:

Vue Cli starter app

We will change this completely. This is a live reload server. This means that every change you do in the project, it will reflect those changes in the GUI. No need to waste valuable seconds refreshing the site manually :).

#3 Create the Weather Component

The project folder should look something like this:

Explorer

In the components folder, create a new file called Weather.vue and add this code:

// Weather.vue

<template>
  <div>
      <h1>My Weather App</h1>
  </div>
</template>

<script>
export default {
  name: 'Weather'
}
</script>

Here we have created a simple component displaying a header tag with “My Weather App”. We will work more on this shortly.

In the App.vue file, we have changed the code to this:

// App.vue

<template>
  <div id="app">
    <Weather />
  </div>
</template>

<script>
import Weather from './components/Weather.vue'

export default {
  name: 'app',
  components: {
    Weather
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

We have only changed the code within the template tag and the script tag.

In the template tag, we removed all the HTML within the div tag and replaced it with our Weather component.

In the script tag, we removed the HelloWorld component and replaced it with our Weather component.

When we save our files, our local server should reload and show us this web page:

Weather app starting point

#4 Get the Weather Data from the Local JSON File

Let’s get started fetching our weather data.

We will be using a simple JSON file for fetching the data.

// weather.json

[
  {
    "id": 1,
    "location": "London",
    "abbr": "s",
    "time": "07:15 pm",
    "temp": 59
  },
  {
    "id": 2,
    "location": "New York",
    "abbr": "hr",
    "time": "12:10 pm",
    "temp": 64
  },
  {
    "id": 3,
    "location": "Los Angeles",
    "abbr": "c",
    "time": "15:15 pm",
    "temp": 77
  },
  {
    "id": 4,
    "location": "Sydney",
    "abbr": "lc",
    "time": "19:35 pm",
    "temp": 85
  },
  {
    "id": 5,
    "location": "Berlin",
    "abbr": "hc",
    "time": "03:15 pm",
    "temp": 55
  }
]

Copy the JSON content in a file called weather.json. Add the file into the root of the public folder of your project.

Change the code in the script section in Weather.json to look like this:

<script>
export default {
  name: "Weather",
  data() {
    return {
      weatherDataList: []
    };
  },
  methods: {
    getWeatherData() {
      fetch("weather.json")
        .then(response => response.json())
        .then(data => (this.weatherDataList = data));
    }
  }
};
</script>

We have created a variable called weatherDataList. We will fill this variable with the data from the JSON file.

Then create a method called getWeatherData. Here we use the fetch API to fetch the data from the JSON file. This returns a promise and we are using the then function to handle the response.

With the fetch API we need to call the json() function which reads the response to the completion. This also returns a promise, so we need to chain a new then method to get the JSON data that we want.

Even though we are fetching the data from a file, we do the exact same thing when fetching data from an URL. Just replace “weather.json” with the API URL.

#5 Display the Raw JSON Data on the Web Page

Add this in the template section of the weather.vue file:

// weather.vue

<template>
  <div>
    <h1>My Weather App</h1>
    <button v-on:click="getWeatherData">Get Weather Data</button>
    <div>{{weatherDataList}}</div>
  </div>
</template>

This is just a simple template to check if are fetching the JSON data correctly.

Notice on the button we have added v-on:click="getWeatherData". This is a click listener which will execute the getWeatherData when clicked.

In the next div, we will display the raw JSON data in the view.

Now, click the button and you should see this as a result:

My Weather app with raw JSON data

Not pretty, but we now have the confidence that the data fetching worked as it should.

#6 Create a User-Friendly GUI

We can now focus on displaying the data in a more user-friendly way.

Change the template section in the Weather.vue file like this:

// Weather.vue

<template>
  <div>
    <h1>My Weather App</h1>
    <button v-on:click="getWeatherData">Get Weather Data</button>
    <div v-for="weatherData in weatherDataList" :key="weatherData.id" class="weather-data">
      <div class="weather-stats">
        <div>
          <span>{{weatherData.time}}</span>
        </div>
        <div>
          <span class="location">{{weatherData.location}}</span>
        </div>
      </div>
      <div class="weather-icon">
        <img :src="`https://www.metaweather.com/static/img/weather/${weatherData.abbr}.svg`">
      </div>
      <div class="weather-temp">
        <span>{{weatherData.temp}}°</span>
      </div>
    </div>
  </div>
</template>

Instead of the raw JSON data, we are using the v-for directive to loop through each element in the weatherDataList. We can then add the properties in the HTML by using the double bracket syntax.

We are using images from https://www.metaweather.com/ to display some beautiful weather logos.

If you try to get the weather data now, you will notice that the app looks horrible. Let’s change that by adding some CSS.

Add styles:

// Weather.json

<style scoped>
.weather-data {
  display: flex;
  align-items: center;
  margin-top: 20px;
  margin-left: 20px;
  border-bottom: 2px solid #ccc;
  padding: 20px;
}

.weather-icon {
  flex-grow: 1;
}

.weather-stats {
  flex-grow: 8;
  text-align: left;
  padding-left: 20px;
}

.weather-stats .location {
  font-size: 30px;
}

.weather-temp {
  flex-grow: 1;
  font-size: 35px;
}

img {
  width: 70px;
}

button {
    padding:10px;
    background-color: #1aa832;
    color: white;
    border: 1px solid #ccc;
}
</style>

I’m not going to go into details about the styles here. We are using flexbox to lay out all the element in the page.

Here is the final result:

My Weather app result

#7 Bonus: Fetching the data using axios

As we saw earlier, we used the fetch API to get the JSON data from our weather.json file.

Fetch has a few shortcomings. Like we demonstrated earlier with fetch, we needed to chain two then functions to the call the get the data. This is simplified with axios.

Let’s replace our current fetch function with axios.

First install to our project. Enter this in the command line from the project folder:

npm install axios

Import axios by placing this right below the <script> tag in Weather.vue:

import axios from 'axios';

Change the getWeatherData method to look like this:

// Weather.vue

getWeatherData() {
      //   fetch("weather.json")
      //     .then(response => response.json())
      //     .then(data => (this.weatherDataList = data));
      axios.get("weather.json").then(response => (this.weatherDataList = response.data));
    }

As you can see, this is a simpler syntax and the app works just the same.

Here is the code for the complete Weather.vue app:

// Weather.vue

<template>
  <div>
    <h1>My Weather App</h1>
    <button v-on:click="getWeatherData">Get Weather Data</button>
    <div v-for="weatherData in weatherDataList" :key="weatherData.id" class="weather-data">
      <div class="weather-stats">
        <div>
          <span>{{weatherData.time}}</span>
        </div>
        <div>
          <span class="location">{{weatherData.location}}</span>
        </div>
      </div>
      <div class="weather-icon">
        <img :src="`https://www.metaweather.com/static/img/weather/${weatherData.abbr}.svg`">
      </div>
      <div class="weather-temp">
        <span>{{weatherData.temp}}°</span>
      </div>
    </div>
  </div>
</template>
<script>
import axios from "axios";
export default {
  name: "Weather",
  data() {
    return {
      weatherDataList: []
    };
  },
  methods: {
    getWeatherData() {
      //   fetch("weather.json")
      //     .then(response => response.json())
      //     .then(data => (this.weatherDataList = data));
      axios
        .get("weather.json")
        .then(response => (this.weatherDataList = response.data));
    }
  }
};
</script>
<style scoped>
.weather-data {
  display: flex;
  align-items: center;
  margin-top: 20px;
  margin-left: 20px;
  border-bottom: 2px solid #ccc;
  padding: 20px;
}

.weather-icon {
  flex-grow: 1;
}

.weather-stats {
  flex-grow: 8;
  text-align: left;
  padding-left: 20px;
}

.weather-stats .location {
  font-size: 30px;
}

.weather-temp {
  flex-grow: 1;
  font-size: 35px;
}

img {
  width: 70px;
}

button {
  padding: 10px;
  background-color: #1aa832;
  color: white;
  border: 1px solid #ccc;
}
</style>

Final Words

Hope you learned something in this tutorial.

If you are new to Vue.js and want to learn more, I highly recommend their excellent official documentation.

If you want to go more in depth, I recommend this great extensive course by Maximillian with over 21 hours of high-quality videos.

Happy coding!

Similar Posts