Vue.js validation

Forms

Want more?

Visit: Vee-Validate

Vuelidate is a simple, lightweight, model-based validation library for Vue applications. Validation rules are added to a validation object where a given component is defined (instead of directly inside the DOM).

What is Vuelidate? 

import { required, minLength, between } 
	from 'vuelidate/lib/validators'

export default {
  data() {  return {
      name: '', age: 0 }
  },
  validations: {
    name: {
      required,
      minLength: minLength(4)
    },
    age: {
      between: between(20, 30)
    }
  }
}
<div>
  <div :class="{ 'form-group--error': $v.name.$error }">
    <label >Name</label>
    <input v-model.trim="$v.name.$model"/>
  </div>
  <div class="error" v-if="!$v.name.required">Field is required</div>
  <div class="error" v-if="!$v.name.minLength">
  	Name must have at least {{$v.name.$params.minLength.min}} letters.</div>
  <div :class="{ 'form-group--error': $v.age.$error }">
    <label >Age</label>
    <input v-model.trim.lazy="$v.age.$model"/>
  </div>
  <div class="error" v-if="!$v.age.between">
  	Must be between {{$v.age.$params.between.min}} and {{$v.age.$params.between.max}}</div>
</div>
$v: {
  name: {
    "required": false,
    "minLength": false,
    "$invalid": true,
    "$dirty": false,
    "$error": false,
    "$pending": false
  },
  age: {
    "between": false
    "$invalid": true,
    "$dirty": false,
    "$error": false,
    "$pending": false
  }
}

Provided validators

import { required, minLength } from 'vuelidate/lib/validators'

export default {
  data() {
    return {
      name: '',
      age: 0,
      submitStatus: null
    }
  },
  validations: {
    name: {
      required,
      minLength: minLength(4)
    }
  },
  methods: {
    submit() {
      console.log('submit!')
      this.$v.$touch()
      if (this.$v.$invalid) {
        this.submitStatus = 'ERROR'
      } else {
        // do your submit logic here
        this.submitStatus = 'PENDING'
        setTimeout(() => {
          this.submitStatus = 'OK'
        }, 500)
      }
    }
  }
}

Forms JS

<form @submit.prevent="submit">
  <div class="form-group" :class="{ 'form-group--error': $v.name.$error }">
    <label class="form__label">Name</label>
    <input class="form__input" v-model.trim="$v.name.$model"/>
  </div>
  <div class="error" v-if="!$v.name.required">Name is required</div>
  <div class="error" v-if="!$v.name.minLength">
    Name must have at least {{$v.name.$params.minLength.min}} letters.</div>
  <button class="button" type="submit" :disabled="submitStatus === 'PENDING'">
    			Submit!</button>
  <p class="typo__p" v-if="submitStatus === 'OK'">
    			Thanks for your submission!</p>
  <p class="typo__p" v-if="submitStatus === 'ERROR'">
    			Please fill the form correctly.</p>
  <p class="typo__p" v-if="submitStatus === 'PENDING'">
    			Sending...</p>
</form>

Forms HTML

import { required } from 'vuelidate/lib/validators'

export default {
  data() {
    return {
      flatA: '',
      flatB: '',
      forGroup: {
        nested: ''
      }
    }
  },
  validations: {
    flatA: { required },
    flatB: { required },
    forGroup: {
      nested: { required }
    },
    validationGroup: ['flatA', 'flatB', 'forGroup.nested']
  }
}

Validation Groups

If you want to create a validator that groups many otherwise unrelated fields together, you can create a validation group.

<div>
  <div class="form-group" :class="{ 'form-group--error': $v.flatA.$error }">
    <label class="form__label">Flat A</label>
    <input class="form__input" v-model.trim="$v.flatA.$model"/>
  </div>
  <div class="error" v-if="!$v.flatA.required">Field is required.</div>
  <div class="form-group" :class="{ 'form-group--error': $v.flatB.$error }">
    <label class="form__label">Flat B</label>
    <input class="form__input" v-model.trim="$v.flatB.$model"/>
  </div>
  <div class="error" v-if="!$v.flatB.required">Field is required.</div>
  <div class="form-group" :class="{ 'form-group--error': $v.forGroup.nested.$error }">
    <label class="form__label">Nested field</label>
    <input class="form__input" v-model.trim="$v.forGroup.nested.$model"/>
  </div>
  <div class="error" v-if="!$v.forGroup.nested.required">Field is required.</div>
  <div class="form-group" :class="{ 'form-group--error': $v.validationGroup.$error }"></div>
  <div class="error" v-if="$v.validationGroup.$error">Group is invalid.</div>
</div>

Validation Groups

import { required, minLength } from 'vuelidate/lib/validators'

export default {
  data() {
    return {
      people: [
        {
          name: 'John'
        },
        {
          name: ''
        }
      ]
    }
  },
  validations: {
    people: {
      required,
      minLength: minLength(3),
      $each: {
        name: {
          required,
          minLength: minLength(2)
        }
      }
    }
  }
}

Collection Validation

import { required } from 'vuelidate/lib/validators'

export default {
  data() {
    return {
      username: ''
    }
  },
  validations: {
    username: {
      required,
     async isUnique (value) {
    if (value === '') return true
    const response = await fetch(`/api/unique/${value}`)
    return Boolean(await response.json())
  } }}
}

Asynchronous validation

Async support is provided out of the box. Just use a validator that returns a promise. Promise's success value is used for validation directly, failed promise just fails the validation and throws the error.

  <div class="error" v-if="!$v.username.isUnique">This username is already registered.</div>

$v values

$v model represents the current state of validation. It does so by defining a set of properties which hold the output of user defined validation functions, following the validations option structure. The presence of those special reserved keywords means that you cannot specify your own validators with that name.

$v methods

A set of methods to control the validation model. Accessible on every level of nesting. All methods are ment to be used on any event handler you wish. There is no extra syntax to decide when the dirty flag should be set. Just use standard @input or @blur bindings.

Visit: Vuelidate

Want more?

Continue to workshop