Published: June 25 2022

Vue 3 + VeeValidate - Show Loading Spinner on Form Submit during HTTP Request to API

Tutorial built with Vue 3.2.33 and VeeValidate 4.5.11

This is a quick example of how to display a loading spinner in Vue 3 with VeeValidate when a form has been submitted and an HTTP (AJAX) request has been sent to the API. A loading spinner indicates to the user that the form has been submitted and the browser is waiting for a response from the API.

Disable submit button while form is submitting

The below example also disables the form submit button while the AJAX request is in progress to prevent the user from double submitting the form by mistake.


VeeValidate is a library for building, validating and handling forms in Vue.js. VeeValidate 4 was recently released and is compatible with Vue 3, the official docs are available at

Vue 3 Loading Spinner Example

The example Vue app contains a form with a single button that submits an HTTP POST request to a fake API endpoint. The fake endpoint waits two seconds to return a response so the loading spinner is displayed and the button is disabled in the form.

Here it is in action: (See on StackBlitz at

Vue 3 + VeeValidate App Component with Loading Spinner

In the script block of the app component, the onSubmit() method returns the result of a fetch HTTP POST request to the API.

The app component template contains a form with a single submit button. The form is built with the VeeValidate <Form /> component and calls the onSubmit() method when the form is submitted. The isSubmitting form state prop is provided to the form template via the scoped slot v-slot="{ isSubmitting }".

Don't forget to return a Promise from onSubmit()!!

The loading spinner shows when the VeeValidate isSubmitting prop is true. For this to work a promise (or async function) must be returned from the onSubmit() function. VeeValidate sets isSubmitting to true while the promise/async function is pending (neither resolved nor rejected).

If you forget to return a promise (I have a few times) the loading spinner will not display at all. You can test by removing the return from the onSubmit() function in the demo.

<script setup>
import { Form } from 'vee-validate';

import { fetchWrapper } from '@/helpers';

function onSubmit() {
    return'/api/fake-end-point', {});

    <div class="card m-3">
        <h5 class="card-header">Vue 3 + VeeValidate - Show Loading Spinner on Form Submit</h5>
        <Form class="card-body" @submit="onSubmit" v-slot="{ isSubmitting }">
            <button class="btn btn-primary" :disabled="isSubmitting">
                <span v-show="isSubmitting" class="spinner-border spinner-border-sm mr-1"></span>


Need Some Vue 3 Help?

Search fiverr for freelance Vue 3 developers.

Follow me for updates

On Twitter or RSS.

When I'm not coding...

Me and Tina are on a motorcycle adventure around Australia.
Come along for the ride!


Supported by