In your VueJS application, you have a form in your application whose data you are submitting to the server asynchronously with the help of Axios.
But there is a problem when the request is being submitted the user can still see the form as it is, and the fields aren't disabled, also there is no feedback to the user of what's going on behind the scenes.
In this short tutorial, lesson let's discuss how we can disable the form and also show a loading spinner at the center of the form during we are submitting the form details to the server via Axios.
Let's dive in
# Form Component Template
We have a standard form with Bootstrap utility classes with two fields title and body. On form submission, we use the v-on directive of Vue to invoke the storePost
method.
<template>
<div id="axiosForm">
<h4 class="font-weight-semibold mb-4">Create a new Post</h4>
<form class="contact-form" @submit.prevent="storePost" method="POST" novalidate="novalidate">
<div class="contact-form-success alert alert-success mt-4" v-if="success">
<strong>Success!</strong> Your post is created.
</div>
<div class="contact-form-error alert alert-danger mt-4" v-if="error">
<strong>Error!</strong> There was an error sending your request.
</div>
<div class="form-row">
<div class="form-group col">
<input type="text" placeholder="Post Title" value="" maxlength="100" class="form-control" name="title" v-model="formData.title">
</div>
</div>
<div class="form-row">
<div class="form-group col">
<textarea maxlength="5000" placeholder="Body" rows="5" class="form-control" name="body" required="" v-model="formData.body"></textarea>
</div>
</div>
<div class="form-row">
<div class="form-group col">
<input type="submit" value="Send Message" class="btn btn-primary btn-lg mb-5">
</div>
</div>
</form>
</div>
</template>
We have also used two data property named success and error to display the successful form submission and error notification respectively.
# Axios Request
We are using the jsonplaceholder dummy API to demonstrate this example. Below is the Axios request that we invoke on form submission.
<script>
export default {
name: 'form-loading-spinner-example',
data(){
return{
success: false,
error: false,
loading: false,
formData : {
title: null,
body: null,
}
}
},
methods:{
storePost(){
this.loading = true,
axios.post("https://jsonplaceholder.typicode.com/posts", this.formData)
.then((res) => {
this.reset();
this.success = true;
console.log(res);
})
.catch((error) => {
this.error = true;
console.log(error)
}).finally(() => {
this.loading = false
});
},
reset(){
this.success = false;
this.error = false;
for(let field in this.formData){
this.formData[field] = null;
}
}
}
}
</script>
Notice that we have defined a data property named loading
which if true denotes that the axios request is currently in progress. By default, it's set to false, once we start the axios request we change it to true and inside the finally
method (which gets executed every time) , we change back the value to false.
# Disable Form Fields
Let's make use of the loading data property in your template to disable all the form fields.
Wrap your form fields inside the fieldset
tag and bind the disabled attribute to the loading property.
<div id="axiosForm">
<h4 class="font-weight-semibold mb-4">Create a new Post</h4>
<form class="contact-form" @submit.prevent="storePost" method="POST" novalidate="novalidate">
<fieldset :disabled="loading">
...
</fieldset>
</form>
</div>
This will ensure that all of the form fields are disabled while axios request is working.
# Show Loading Spinner
Let's move on to the next part, and see how we can utilize the loading
property to also show a loading spinner gif just at the center of the form so that user gets the feedback that the request is still processing.
Add a new div named loader inside the component's root div.
<div id="axiosForm">
<div class="loader" v-if="loading"></div>
...
</div>
We are using v-if directive bound to the loading property.
Include the following CSS to your component
<style scoped>
#axiosForm{ /* Components Root Element ID */
position: relative;
}
.loader{ /* Loader Div Class */
position: absolute;
top:0px;
right:0px;
width:100%;
height:100%;
background-color:#eceaea;
background-image: url('../assets/ajax-loader.gif');
background-size: 50px;
background-repeat:no-repeat;
background-position:center;
z-index:10000000;
opacity: 0.4;
filter: alpha(opacity=40);
}
</style>
Once applied it will show the loading Gif just at the center of your form component.
# Demo