Async in Vuejs -Part 2
Let’s create a random cocktail app
In Part 1 of this tutorial we have seen how to create a skeleton card that can be used as a loading feedback instead of a classic boring spinner.
If you miss it you can check it here:
https://medium.com/@FrancescoZ/async-in-vue-js-part-1-28d96f751a2e
Today we are going to building this:
A random cocktail single page app. We will discover how to fetch data from an API and use the previously created skeleton card component to improve the user experience.
I will keep things simple by just using a single component with all the logic inside it, so no state management library will be used. Keep in mind that is just an example, you should always keep your state separated from the components.
Let’s get started!
Implementation
Before starting, let me just say that we are only going to focus only on the asynchronous parts and not on the design. As always you can find all the code on GitHub:
https://github.com/FrancescoSaverioZuppichini/random-cocktails-app
Again, we use drawio2vuejs to quickly create the projecj and, again, we are going to use Vuetify as main UI framework.
https://github.com/FrancescoSaverioZuppichini/DrawIo2Vuejs
First, we create the basic project template by calling.
vue init vuetifyjs/webpack random-cocktails-app
We need two components, Cocktails
and Cocktail
. So just create the draw.io diagram and call the drawio2vuejs cl as we did in the last part.
Cocktails
will hold all the logic behind calling the API and display the correct content, in our case, a list of cocktails. So, open Cocktails.vue
and add in the data field:
//Cocktails.vue
...
data: function() {
return {
isLoading: false,
cocktails: []
}
},
...
Where isLoading
will be used to know when we need to display our loading feedback. We also need a method that will get and add a new random cocktail, for simplicity we called it getMore
//Cocktails.vue
...
methods: {
getMore() {
this.isLoading = true
axios.get(API_URL)
.then(({ data }) => {
var cocktail = data.drinks[0]
this.cocktails.push(cocktail)
cocktail.ingredients = this.createIngrediens(cocktail)
this.isLoading = false
})
.catch(err => this.isLoading = false)
},
}
...
You can see isLoading
is set to true before calling the endpoint and toggled after. Since the returned JSON has not a real array with all the ingredients, I have created a util method called createIngredients
to do so.
I added a button below the last Cocktail to trigger the previously created method and fetch a new one every time. Easily the template is composed by a list of Cocktail
component and some Vuetify component to create the single page layout:
<template>
<v-container>
<transition-group name="fade" class='layout row wrap align-center' mode="out-in">
<v-flex xs12 :key="cocktail.idDrink" v-for="cocktail in cocktails">
<cocktail :cocktail="cocktail" class='mb-2'>
</cocktail>
</v-flex>
</transition-group>
<v-flex xs12>
<v-layout column align-center>
<v-btn primary @click="getMore()"> Get More</v-btn>
</v-layout>
</v-flex>
</v-container>
</template>
I have also added a Vue.js transition-group
element to create a nice fade in animation when a new Cocktail appears. If we try the app now, we can notice that everything works but we are still missing something.
Can you spot it?
Yes! We are missing a loading feedback. Let’s use the skeleton card that we create in the last part of this tutorial series. You can install it by just:
npm install -S skeleton-card-vuejs
Then, import as a normal component:
import SkeletonCard from 'skeleton-card-vuejs'
Now add it the Cocktails.vue
template and set the correct props to mimic the content we want to load. In this case, we do not a header and the orientation is horizontal. Also, we want to see it only when isLoading
is true.
//Cocktails.vue<template>
<v-container>
<transition-group name="fade" class='layout row wrap align-center' mode="out-in">
<v-flex xs12 :key="cocktail.idDrink" v-for="cocktail in cocktails">
<cocktail :cocktail="cocktail" class='mb-2'>
</cocktail>
</v-flex>
<v-flex xs12 v-show="isLoading" key='loading'>
<skeleton-card class='skeleton-card--opacity' :hasHeader="false" :isHorizontal="true"> </skeleton-card>
</v-flex>
</transition-group>
....
</v-container>
</template>
And then it will appear when a new cocktail has been fetched
If you want to discover new cocktails, you can find the app here:
https://francescosaveriozuppichini.github.io/random-cocktails-app/
Conclusion
In this last part of “Async in Vue.js” we have seen how to properly load some content with axios and show a loading feedback using a skeleton card to give to the user fist clue of what is going to be displayed and a better experience.
You may also find these articles interesting:
How to make API calls in a smart way
By keeping all the endpoints in globally shared file
codeburst.io
If you have any feedbacks, please leave a comment.
Thank you for reading
Francesco Saverio Zuppichini