IMG-LOGO

How to create loading popup component in Vue.js?

andy - 04 Oct, 2018 5390 Views 0 Comment

In this tutorial, you will learn how to pop up a loading message in Vue.js. So why you need a loading message? Well, the loading message is useful, especially you want to let your users know when a site is processing a request. For example, when submitting a registration form details, it may take a while to submit the data. Somehow, we need to notify our users we are processing their request. We are going to create a Vue.js component for our loading message, so they can be re-used again. During this tutorial, you will also learn how to structure your project folders as we are going to use Vuex. We will also use Vue.js router as well to demonstrate how it works. So let's get started with the simple tutorial.

I am not going to use CLI in here. All of the Vue.js and Vuex will use the script tag path.

The first step is to create the following folders to organize our simple demo project files. Note: there is rule right or wrong on how to structure your vue.js project folders. Feel free to make your own folder structure. As long as it is organized neatly, that will make easier for other programmers to view your project files.

++++++ app.html (MAIN FILE)
++++++ assets (FOLDER)
++++++++++++ components (FOLDER)
++++++++++++++++++++++++ loader (FOLDER)
++++++++++++ pages (FOLDER)
++++++++++++++++++++++++ home (FOLDER)
++++++++++++ css (FOLDER)
++++++++++++ js (FOLDER)
++++++++++++ store (FOLDER)
++++++++++++++++++ modules (FOLDER)
++++++++++++++++++++++++ loader (FOLDER)

Let's create the app.html which is going to be the main demo file.

<!doctype>
<html>
<head>
    <title>How to create a loading message in Vue.js</title>
	<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">
    <link href="assets/css/style.css" type='text/css' rel='stylesheet'>
    <script src="assets/js/vue.min.dev.js"></script>
	<script src="assets/js/vuex.min.js"></script>
	<script src="assets/js/vue-router.min.js"></script>
</head>
<body>
    <div id="app">
        <loader-component></loader-component>
        <router-view></router-view>
    </div>
    <script src="assets/js/main.js" type="module"></script>
</body>
</html>

As you notice on above code, you will see I have included scripts path for Vue.js (debug version), vuex.min.js, vue-router.min.js and main.app file. Vuex.js script will be used as a state management which will hold the values to display the loading message. While the vue-router.min.js script will be used to navigate pages around Vue.js app. The last main.js script will be the main javascript application. As we are going to import files in this main javascript file, we need to set the type of this file as ECMAScript module. In order for the browsers to understand this type, we need to set the type of the script as module rather than script. The loader-component html tag will be used to load the message, while the router-view tag will be used to display the Vue.js component.

We are now going to create a Vuex store that will hold the temporary data for our loading message. Under the assets\store\modules\loader folder, lets create a javascript file named loader-store.js. This file will have the following javascript code.

const state = {
	LOADER_loadingStatus: false,
	LOADER_loadingMesage: 'Loading...'
}

const getters = {
	getLoadingStatus: state => {
		return state.LOADER_loadingStatus;
	},
	
	getLoadingMessage: state => {
		return state.LOADER_loadingMesage;
	}
}

const mutations = {
	hideLoadingMessage(state){
		state.LOADER_loadingStatus = false;
		state.LOADER_loadingMesage = "";
	},
	
	showLoadingMessage(state, message){
		state.LOADER_loadingStatus = true;
		state.LOADER_loadingMesage = message;
	}
}

const actions = {
	hideLoadingMessage: (context) => {
		context.commit("hideLoadingMessage");
	},
	
	showLoadingMessage: (context, payload) => {
		context.commit("showLoadingMessage", payload);
	}
}

const loaderStore = {
	state,
	getters,
	actions,
	mutations
}

export default loaderStore;

If we have a look on the above code, we define two state variables. The first store variable is a flag status. It will be used to tell whether the loading message is currently being used or loaded to the screen. The second store variable is used for displaying the message. We then have our store getters, mutations and actions for hiding and showing the loading message. Once this file has already been created, we then create our vuex store file that will import this javascript file. Under the Under the assets\store\modules folder, create a javascript module file named store.js. Here is the code for our store.js file.

import loaderStore from './modules/loader/loader-store.js';

Vue.use(Vuex);

const store = new Vuex.Store({
	modules: {
		loaderStore
	}
})

export default store;

The next file we need to create is the loader component. Under the assets/components/loader folder, we create a javascript component file named loader. Here is the code for the loader component file.

var loaderComponent = Vue.component('loader-component', {
	computed: {
        ...Vuex.mapGetters([
            'getLoadingStatus',
            'getLoadingMessage'
        ])
	},
	
	template: `
	  <div class='loader-container' :class='{"show": getLoadingStatus, "hidden": !getLoadingStatus}'>
		<div class="loader-content">
		  <i class="fas fa-sync fa-spin"></i>
		  <div class="loading">
			{{ getLoadingMessage }}
		  </div>
		</div>
	  </div>
	`
})

export default loaderComponent;

As you know we are using the font-awesome to display our spinning icon. You can identify this by looking at the HTML i tag contains the CSS class name of fas fa-sync fa-spin. We set the Vuex Get and map it to the computed properties. By default, this loading tag will be hidden until we call our Vuex store functions to set the flag status. You can easily identify by looking at the if condition applied in the loading CSS class where it will hide it if the getLoadingStatus is equal to false.

The next part we need to do is to style our loading message. We use the following css style.

.loader-container {
    position: fixed;
    width: 100%;
    height: 100%;
    background: rgba(0,0,0,0.8);
    left: 0;
    top: 0;
}

.loader-content {
    position: absolute;
    top: 45%;
    left: 50%;
    transform: translateX(-50%);
    border-radius: .3rem;
    padding: 20px;
    box-sizing: border-box;
    background: white;
    box-shadow: 0 0 .1rem #fefefe;
    text-align: center;
}

.loading {
    text-align: center;
}

.show {
    visibility: visible;
    opacity: 1;
    z-index: 1;
    transition: opacity 0.5s ease-out, visibility 0.5s ease-out, z-index 0.5s ease-out;
}

.hidden {
    visibility: hidden;
    opacity: 0;
    z-index: 0;
    transition: opacity 0.5s ease-out, visibility 0.5s ease-out, z-index 0.5s ease-out;
}

Lets create our homepage component which will have a button to display and automatically hide the loading message in 3 seconds. Under the assets\pages\home folder, create a javascript file named home.js. The home component will have the following code.

var homePageComponent = Vue.component('home-page', {
	template: `
		<div class="container">
			<button type="button" v-on:click="showMessage()">Show Loading Message</button>
		</div>
	`,
	
	methods:{
		showMessage(){
			this.$store.dispatch("showLoadingMessage", "Please wait while we process your request...");
			var vStore = this.$store;
			setTimeout(function(){
				vStore.dispatch("hideLoadingMessage");
			}, 3000);
		}
	}
})

export default homePageComponent;

We add some style to place the sample button in the center of the page. You can append the following css style.

.container{
	text-align:center;
	margin-top:20%;
}

button{
	padding:20px;
	border-radius:5px;
}

Once this is done, we need to create a router file that will load all our pages component. Under the assets\js folder, we create a javascript file named router.js. Here is the code for our router.js file.

import homePageComponent from '../pages/home/home.js';

var appRoutes = [
	{ 
        path: '', 
        component: homePageComponent
    }
]

const router = new VueRouter({
  routes : appRoutes
})

export default router;

The final file that we need to create is the main.js file. Here is the full code for the main.js file.

import loaderComponent from '../components/loader/loader.js';
import router from './router.js';
import store from '../store/store.js';

new Vue({
	router,
    store: store,
    components: {
        loaderComponent
    }
}).$mount('#app')

Download Files

You can download the files on the following link.

Download

Demo

To view the demo file, please click this link to see it in action.

If you have any question regarding with this tutorial, please post your message below.

Comments

There are no comments available.

Write Comment
0 characters entered. Maximum characters allowed are 1000 characters.

Related Articles