Published: August 01 2018

Vue.js + VeeValidate - Form Validation Example

Example built with Vue 2.5.2 and VeeValidate 2.1.0

Other versions available:

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

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 + VeeValidate example is all done with Bootstrap 4 CSS.

Here it is in action: (See on CodeSandbox at

Vue.js + VeeValidate 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 is implemented using the v-validate attribute from the VeeValidate library, it supports a bunch of validators out of the box including required, minlength and email.

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.

  <div class="jumbotron">
      <div class="container">
          <div class="row">
              <div class="col-sm-8 offset-sm-2">
                      <h2>Vue.js Form Validation</h2>
                      <form @submit.prevent="handleSubmit">
                          <div class="form-group">
                              <label for="firstName">First Name</label>
                              <input type="text" v-model="user.firstName" v-validate="'required'" id="firstName" name="firstName" class="form-control" :class="{ 'is-invalid': submitted && errors.has('firstName') }" />
                              <div v-if="submitted && errors.has('firstName')" class="invalid-feedback">{{ errors.first('firstName') }}</div>
                          <div class="form-group">
                              <label for="lastName">Last Name</label>
                              <input type="text" v-model="user.lastName" v-validate="'required'" id="lastName" name="lastName" class="form-control" :class="{ 'is-invalid': submitted && errors.has('lastName') }" />
                              <div v-if="submitted && errors.has('lastName')" class="invalid-feedback">{{ errors.first('lastName') }}</div>
                          <div class="form-group">
                              <label for="email">Email</label>
                              <input type="email" v-model="" v-validate="'required|email'" id="email" name="email" class="form-control" :class="{ 'is-invalid': submitted && errors.has('email') }" />
                              <div v-if="submitted && errors.has('email')" class="invalid-feedback">{{ errors.first('email') }}</div>
                          <div class="form-group">
                              <label for="password">Password</label>
                              <input type="password" v-model="user.password" v-validate="{ required: true, min: 6 }" id="password" name="password" class="form-control" :class="{ 'is-invalid': submitted && errors.has('password') }" />
                              <div v-if="submitted && errors.has('password')" class="invalid-feedback">{{ errors.first('password') }}</div>
                          <div class="form-group">
                              <button class="btn btn-primary">Register</button>

export default {
    name: 'app',
    data () {
        return {
            user: {
                firstName: '',
                lastName: '',
                email: '',
                password: ''
            submitted: false
    methods: {
        handleSubmit(e) {
            this.submitted = true;
            this.$validator.validate().then(valid => {
                if (valid) {
                    alert('SUCCESS!! :-)\n\n' + JSON.stringify(this.user))

Vue.js + VeeValidate 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 VeeValidate and calling Vue.use(VeeValidate);.

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

import Vue from "vue";
import VeeValidate from "vee-validate";

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