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.
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.
import Vue from 'vue';
import Vuelidate from 'vuelidate';
import App from 'App.vue';
Vue.use(Vuelidate);
new Vue({
el: '#app',
render: h => h(App)
});
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 && $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.
}
<template>
<form>
<input type="text" v-model="emailValue"/>
<p v-if="!$v.emailValue.required">The email field is required!</p>
<p v-if="!$v.emailValue.email">The input must be a proper email!</p>
</form>
</template>
<script>
import { required, email } from 'vuelidate/lib/validations'
export default {
data() {
return {
emailValue: ''
}
},
validations: {
emailValue: {
required,
email
}
}
}
</script>
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.
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.
export const TomValidator = (value, component) => {
return value === 'tom';
}
...
<script>
import { TomValidator } from './tom-validator';
export default {
data() {
return {
inputField: ''
}
},
validators: {
inputField: {
TomValidator
}
}
}
</script>
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.
export const MatchValidator = (stringToMatch) => {
return (value, component) => value === stringToMatch;
}
...
<script>
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...
}
}
}
</script>
Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.
Sign up