URL: https://www.progressiverobot.com/vuejs-model-form-validation-vuelidate/

While the most beginner-friendly approach to form validation in Vue.js might be through template-based forms, a much more flexible way is to validate the model instead. Model-based validation tends to be easier to understand and change for larger apps, moving the visual clutter from the template to the model and reducing it significantly. The most well-known library to accomplish this in <^>Vue<^> is through Vuelidate.

Installation

validation illustration for: Installation

As usual, <^>Vuelidate<^> can be installed from NPM or Yarn.

				
					
# Yarn

$ yarn add vuelidate



# NPM

$ npm install vuelidate --save

				
			

Then, in your app bootstrap, enable the <^>Vuelidate<^> plugin.

				
					
[label main.js]

import Vue from 'vue';

import Vuelidate from 'vuelidate';

import App from 'App.vue';



Vue.use(Vuelidate);



new Vue({

  el: '#app',

  render: h =&gt; h(App)

});

				
			

Field Validation

To validate fields, add a definition object for properties in your <^>data<^> model to the <^>validations<^> property of your component. Then import validation functions from <^>vuelidate/lib/validations<^> (or custom ones you create). You will then be able to bind to the data property via <^>v-model<^> as usual. Validation information will be stored in <^>this.$v[propertyName]<^>.

$v's Schema:

				
					
$v[propertyName]: {

  $dirty: boolean, // Whether or not this field has been interacted with yet.

  $invalid: boolean, // If this field is current valid or invalid, regardless of whether or not it is "dirty"

  $error: boolean, // Shortcut for $invalid &amp;&amp; $dirty

  $pending: boolean, // Whether or not there is a pending validation (for async validations)

  $each: object // Holds all the validations for looped models.

  [YourValidationName]: boolean // The state of the validations defined on this property validations. (ie. if you have the 'required' validator, there would be a boolean 'required' property here, and so forth.)

  [Nested]: object // You can nest values in your model here as well, and the validation properties will be added to each nested field.

}

				
			
				
					
&lt;template&gt;

  &lt;form&gt;

    &lt;input type="text" v-model="emailValue"/&gt;

    &lt;p v-if="!$v.emailValue.required"&gt;The email field is required!&lt;/p&gt;

    &lt;p v-if="!$v.emailValue.email"&gt;The input must be a proper email!&lt;/p&gt;

  &lt;/form&gt;

&lt;/template&gt;



&lt;script&gt;

import { required, email } from 'vuelidate/lib/validations'



export default {

  data() {

    return {

      emailValue: ''

    }

  },



  validations: {

    emailValue: {

      required,

      email

    }

  }

}

&lt;/script&gt;

				
			

Built-In Validators

<^>Vuelidate<^> provides these validators by default. They can be imported from <^>vuelidate/lib/validators<^>. If you're using Webpack 2 or Rollup with tree shaking, any validators not used in your project will not be bundled with it.

  • <^>required()<^> – This field cannot be empty.
  • <^>minLength(length: number)<^> – Minimum length of the field. Works on strings and arrays.
  • <^>maxLength(length: number)<^> – Maximum length of the field. Works on strings and arrays.
  • <^>between(min, max)<^> – Requires a number to be between the minimum and maximum values.
  • <^>alpha()<^> – Only allows alphabetic characters.
  • <^>alphaNum()<^> – Only allows alphanumeric characters.
  • <^>email()<^> – Allow only valid emails.
  • <^>sameAs(fieldName: string | getFieldName: function -> string)<^> – Allows you to require the input to be the same as another field, specified by fieldName or a function.
  • <^>or(validators…)<^> – Valid when at least one of the specified validators is valid.
  • <^>and(validators…)<^> – Valid when all of the specified validators are valid.

Custom Validatiors

A custom validator in Vuelidate is simply a function that returns a boolean or a promise that resolves to a boolean.

If you want to ensure that fields contain only the word "tom", you might write a validator like this.

				
					
[label tom-validator.js]

export const TomValidator = (value, component) =&gt; {

  return value === 'tom';

}

				
			
				
					
[label MyComponent.vue]

...

&lt;script&gt;

import { TomValidator } from './tom-validator';

export default {

  data() {

    return {

      inputField: ''

    }

  },



  validators: {

    inputField: {

      TomValidator

    }

  }

}

&lt;/script&gt;

				
			

You might want to go a step further and allow a string to be specified that must be matched. In that case, just create a higher-order function that returns the validator function, like so.

				
					
[label match-validator.js]

export const MatchValidator = (stringToMatch) =&gt; {

  return (value, component) =&gt; value === stringToMatch;

}

				
			
				
					
[label MyComponent.vue]

...

&lt;script&gt;

import { MatchValidator } from './match-validator';

export default {

  data() {

    return {

      inputField: ''

    }

  },



  validators: {

    inputField: {

      MatchValidator: MatchValidator('rupert')

      // Only allows inputField to contain 'rupert.' One might Wonder why the field even exists then...

    }

  }

}

&lt;/script&gt;