Form Validation
Base Example
Form validation is natively supported by the browser, but sometimes different browsers will handle things in a manner which makes relying on it a bit tricky. Even when validation is supported perfectly, there may be times when custom validations are needed and a more manual, Vue-based solution may be more appropriate. Let’s begin with a simple example.
Given a form of three fields, make two required. Let’s look at the HTML first:
<form
id="app"
@submit="checkForm"
action="https://vuejs.org/"
method="post"
>
<p v-if="errors.length">
<b>Please correct the following error(s):</b>
<ul>
<li v-for="error in errors">{{ error }}</li>
</ul>
</p>
<p>
<label for="name">Name</label>
<input
id="name"
v-model="name"
type="text"
name="name"
>
</p>
<p>
<label for="age">Age</label>
<input
id="age"
v-model="age"
type="number"
name="age"
min="0">
</p>
<p>
<label for="movie">Favorite Movie</label>
<select
id="movie"
v-model="movie"
name="movie"
>
<option>Star Wars</option>
<option>Vanilla Sky</option>
<option>Atomic Blonde</option>
</select>
</p>
<p>
<input
type="submit"
value="Submit"
>
</p>
</form>
Let’s cover it from the top. The <form>
tag has an ID that we’ll be using for the Vue component. There’s a submit handler that you’ll see in a bit, and the action
is a temporary URL that would point to something real on a server someplace (where you have backup server-side validation of course).
Beneath that there is a paragraph that shows or hides itself based on an error state. This will render a simple list of errors on top of the form. Also note we fire the validation on submit rather than as every field is modified.
The final thing to note is that each of the three fields has a corresponding v-model
to connect them to values we will work with in the JavaScript. Now let’s look at that.
const app = new Vue({
el: '#app',
data: {
errors: [],
name: null,
age: null,
movie: null
},
methods:{
checkForm: function (e) {
if (this.name && this.age) {
return true;
}
this.errors = [];
if (!this.name) {
this.errors.push('Name required.');
}
if (!this.age) {
this.errors.push('Age required.');
}
e.preventDefault();
}
}
})
Fairly short and simple. We define an array to hold errors and set null
values for the three form fields. The checkForm
logic (which is run on submit remember) checks for name and age only as movie is optional. If they are empty we check each and set a specific error for each. And that’s really it. You can run the demo below. Don’t forget that on a successful submission it’s going to POST to a temporary URL.
Using Custom Validation
For the second example, the second text field (age) was switched to email which will be validated with a bit of custom logic. The code is taken from the StackOverflow question, How to validate email address in JavaScript?. This is an awesome question because it makes your most intense Facebook political/religious argument look like a slight disagreement over who makes the best beer. Seriously - it’s insane. Here is the HTML, even though it’s really close to the first example.
<form
id="app"
@submit="checkForm"
action="https://vuejs.org/"
method="post"
novalidate="true"
>
<p v-if="errors.length">
<b>Please correct the following error(s):</b>
<ul>
<li v-for="error in errors">{{ error }}</li>
</ul>
</p>
<p>
<label for="name">Name</label>
<input
id="name"
v-model="name"
type="text"
name="name"
>
</p>
<p>
<label for="email">Email</label>
<input
id="email"
v-model="email"
type="email"
name="email"
>
</p>
<p>
<label for="movie">Favorite Movie</label>
<select
id="movie"
v-model="movie"
name="movie"
>
<option>Star Wars</option>
<option>Vanilla Sky</option>
<option>Atomic Blonde</option>
</select>
</p>
<p>
<input
type="submit"
value="Submit"
>
</p>
</form>
While the change here is small, note the novalidate="true"
on top. This is important because the browser will attempt to validate the email address in the field when type="email"
. Frankly it may make more sense to trust the browser in this case, but as we wanted an example with custom validation, we’re disabling it. Here’s the updated JavaScript.
const app = new Vue({
el: '#app',
data: {
errors: [],
name: null,
email: null,
movie: null
},
methods: {
checkForm: function (e) {
this.errors = [];
if (!this.name) {
this.errors.push("Name required.");
}
if (!this.email) {
this.errors.push('Email required.');
} else if (!this.validEmail(this.email)) {
this.errors.push('Valid email required.');
}
if (!this.errors.length) {
return true;
}
e.preventDefault();
},
validEmail: function (email) {
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\