Template-Based Form Validation with Vue.js and vee-validate

Joshua Bemenderfer

Client-side form validation is a must-have if you want to give users a good idea of what form input they should be entering and avoid accidental typos. One of the simplest ways to do so is with template-based validation. This allows you to validate your forms by adding attributes to inputs. The most mature solution to do this in Vue is with vee-validate.


vee-validate can be installed from NPM or Yarn, like most Vue plugins.

# Yarn
$ yarn add vee-validate
$ npm install vee-validate --save

Then, in your app bootstrap, make sure you enable the vee-validate plugin.


import Vue from 'vue';
import VeeValidate from 'vee-validate';
import App from 'App.vue';


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

Field Validation

Field validation is pretty easy. You just need to add a v-validate attribute (set to the value on the model that you wish to validate, generally the best way to do it) to enable vee-validate, add a data-vv-rules attribute with the field’s rules, and add a name attribute to the field if there isn’t one already. Any errors will be collected in the errors object for you to deal with as you please.

    <input type="text" name="email" v-model="emailValue" v-validate="emailValue" data-vv-rules="required|email"/>
    <p v-if="errors.has('email')">{{ errors.first('email') }}</p>

export default {
  data() {
    return {
      emailValue: ''

Built-In Rules

At the time of writing, vee-validate comes with these rules built in. They can be combined and arranged at will. For more information, see the documentation.

  • after:{target} - Only allow dates after the one specified by {target}. Requires the date_format rule to be present.
  • alpha - Only allow alphabetic characters.
  • alpha_dash - Allow alphabetic characters, numbers, dashes, and underscores.
  • alpha_num - Allow alphabetic characters and numbers.
  • alpha_spaces - Allow alphabetic characters and spaces.
  • before:{target} - Only allow dates before the one specified by {target}. Requires the date_format rule to be present.
  • between:{min},{max} - Allow numbers between {min} and {max}.
  • confirmed:{target} - Input must have the same value as the target input, specified by {target} as the target field’s name.
  • credit_card - Only allow valid credit card numbers.
  • date_between:{min,max} - Only allow dates between the ones specified by {min} and {max}. Requires the date_format rule to be present.
  • date_format:{format} - Only allow the input to be a valid date in the {format} specified. (MomentJS formats)
  • decimal:{decimals?} - Allow numeric values with decimals. Optionally limit the number of decimal places according to {decimals?}.
  • digits:{length} - Only allow numberic input with a specified number of digits according to {length}.
  • dimensions:{width},{height} - Only allow images of the specified dimensions. (For file inputs.)
  • email - Allow valid emails.
  • ext:[extensions] - Allow files only if the file name contains one of the specified [extensions]. (For file inputs.)
  • image - Only allow images to be uploaded. (For file inputs.)
  • in:[list] - Only allow values specified in [list].
  • ip - Only allow valid ipv4 addresses.
  • max:{length} - Limit a numeric value to {length} number of characters.
  • max_value:{value} - Limit a numeric value to {value}.
  • mimes:[list] - Only allow files with a mime type included in [list].
  • min:{length} - Require a numeric value to be at least {length} number of characters.
  • min_value:{value} - Require a numeric value to be at least {value}.
  • not_in:[list] - The input value must not be in [list].
  • numeric - Require the input value to be numeric.
  • regex:{pattern} - Match against a regular expression specified by {pattern}.
  • required - Allows only non-empty values.
  • size:{kb} - An uploaded file may not be larger than the value specified by {kb} (in kilobytes).
  • url:{require_protocol?} - The input must be a valid URL. Will also require the protocol to be specified if {require_protocol?} is true.

Displaying Errors

Errors are collected in the errors object on your component, but it’s entirely up to you how they should be rendered. vee-validate provides a few helper methods to make it easier to collect various types of errors.

  • errors.first(‘fieldName’) Returns the first validation error on the field with the specified name.
  • errors.collect(‘fieldName’) Returns all validation errors on the field with the specified name.
  • errors.has(‘fieldName’) Boolean. true if the specified field has one or more errors, false otherwise. Useful for applying classes on the input element.
  • errors.all() Returns an array of all error messages.
  • errors.any() true if there are any errors on any field in the component. false otherwise.

Custom Validatiors

The simplest way to define global app custom validators is to use the Validator.extend() method provided by vee-validate. A validator consists of an object with two function properties: getMessage(field, params) -> string and validate(value, params) -> boolean | Promise<{valid: boolean}>.

Here’s an example validator that requires the input to contain the word bacon (for better or for worse.)


import { Validator } from 'vee-validate';

Validator.extend('bacon', {
  getMessage: field => {
    return `Field ${field} does not contain the word 'bacon'!`;
  // Returns a boolean value
  validate: value => {
    return value.indexOf('bacon') !== -1;


  • vee-validate is designed with localization in mind from the start and as such has less-than-stellar default error messages. Translation and localization is an advanced topic and will vary significantly depending on your app structure. You can see vee-validate’s documentation for it here
  • You can ignore validating a field when it first loads with the .initial modifier. on the v-validate attribute.
  Tweet It

🕵 Search Results

🔎 Searching...