Published: February 27 2019

Vue.js + Vuelidate - Form Validation Example

Example built with Vue 2.6.7 and Vuelidate 0.7.4

Other versions available:

This is a quick example of how to setup form validation in Vue.js with the Vuelidate library. The example is a simple registration form with pretty standard fields for first name, last name, email, password and confirm password. All fields are required, the email field must be a valid email address, the password field must have a min length of 6 and must match the confirm password field.

I've setup the form to validate on submit rather than as soon as each field is changed, this is implemented with a submitted field in the app component that is set to true when the form is submitted for the first time.

Styling of the Vue.js + Vuelidate example is all done with Bootstrap 4 CSS.

Here it is in action: (See on CodeSandbox at

Vue.js + Vuelidate Form Validation App Component

The app component template contains all the html markup for displaying the example registration form in your browser. The form input fields use the v-model attribute to bind to properties of the user object in the app component data. Validation rules are set in the validations options of the Vue component, Vuelidate supports a bunch of validators out of the box including required, email, minLength and sameAs.

The form binds the submit event to the handleSubmit(e) method in the app component using the Vue event binding @submit.prevent="handleSubmit", .prevent prevents the default browser form submit behaviour (equivalent of putting e.preventDefault() in the handleSubmit method).

Validation messages are displayed only after the user attempts to submit the form for the first time, this is controlled with the submitted data property of the app component. If you prefer to show validation messages as soon as each input is touched simply remove all references to the submitted property.

    <div class="jumbotron">
        <div class="container">
            <div class="row">
                <div class="col-sm-8 offset-sm-2">
                        <h2>Vue.js + Vuelidate - Form Validation</h2>
                        <form @submit.prevent="handleSubmit">
                            <div class="form-group">
                                <label for="firstName">First Name</label>
                                <input type="text" v-model="user.firstName" id="firstName" name="firstName" class="form-control" :class="{ 'is-invalid': submitted && $v.user.firstName.$error }" />
                                <div v-if="submitted && !$v.user.firstName.required" class="invalid-feedback">First Name is required</div>
                            <div class="form-group">
                                <label for="lastName">Last Name</label>
                                <input type="text" v-model="user.lastName" id="lastName" name="lastName" class="form-control" :class="{ 'is-invalid': submitted && $v.user.lastName.$error }" />
                                <div v-if="submitted && !$v.user.lastName.required" class="invalid-feedback">Last Name is required</div>
                            <div class="form-group">
                                <label for="email">Email</label>
                                <input type="email" v-model="" id="email" name="email" class="form-control" :class="{ 'is-invalid': submitted && $$error }" />
                                <div v-if="submitted && $$error" class="invalid-feedback">
                                    <span v-if="!$">Email is required</span>
                                    <span v-if="!$">Email is invalid</span>
                            <div class="form-group">
                                <label for="password">Password</label>
                                <input type="password" v-model="user.password" id="password" name="password" class="form-control" :class="{ 'is-invalid': submitted && $v.user.password.$error }" />
                                <div v-if="submitted && $v.user.password.$error" class="invalid-feedback">
                                    <span v-if="!$v.user.password.required">Password is required</span>
                                    <span v-if="!$v.user.password.minLength">Password must be at least 6 characters</span>
                            <div class="form-group">
                                <label for="confirmPassword">Confirm Password</label>
                                <input type="password" v-model="user.confirmPassword" id="confirmPassword" name="confirmPassword" class="form-control" :class="{ 'is-invalid': submitted && $v.user.confirmPassword.$error }" />
                                <div v-if="submitted && $v.user.confirmPassword.$error" class="invalid-feedback">
                                    <span v-if="!$v.user.confirmPassword.required">Confirm Password is required</span>
                                    <span v-else-if="!$v.user.confirmPassword.sameAsPassword">Passwords must match</span>
                            <div class="form-group">
                                <button class="btn btn-primary">Register</button>

    import { required, email, minLength, sameAs } from "vuelidate/lib/validators";

    export default {
        name: "app",
        data() {
            return {
                user: {
                    firstName: "",
                    lastName: "",
                    email: "",
                    password: "",
                    confirmPassword: ""
                submitted: false
        validations: {
            user: {
                firstName: { required },
                lastName: { required },
                email: { required, email },
                password: { required, minLength: minLength(6) },
                confirmPassword: { required, sameAsPassword: sameAs('password') }
        methods: {
            handleSubmit(e) {
                this.submitted = true;

                // stop here if form is invalid
                if (this.$v.$invalid) {

                alert("SUCCESS!! :-)\n\n" + JSON.stringify(this.user));

Vue.js + Vuelidate Form Validation Base Vue Instance

There isn't much going on in the base Vue instance other than the standard stuff. Validation is configured on the Vue instance by importing Vuelidate and calling Vue.use(Vuelidate);.

The options passed to the Vue instance tell it to render the App component inside the #app html element.

import Vue from 'vue';
import Vuelidate from 'vuelidate';

import App from './app/App';


new Vue({
    el: '#app',
    render: h => h(App)


Need Some Vue Help?

Search fiverr for freelance Vue 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