VeeValidate server side validations
Johan Baaij
Posted on February 2, 2020
In this post we'll look at how to add a VeeValidate rule for validating a value with an API endpoint. A scenario where such a rule is useful could be checking if a username is unique.
Rather than displaying an error after the form is submitted, we'd like to inform the user right away that their username is already taken.
We'll start with this simple component using a ValidationObserver
and ValidationProvider
.
<template>
<ValidationObserver v-slot="{ invalid }">
<ValidationProvider name="username" rules="required" v-slot="{ errors }">
<p>
<input placeholder="username" v-model="username" type="text">
<br>
<span id="error">{{ errors[0] }}</span>
</p>
</ValidationProvider>
<button @click="sendForm" :disabled="invalid" type="button">Submit</button>
</ValidationObserver>
</template>
<script>
import { ValidationProvider, ValidationObserver, extend } from "vee-validate";
import { required } from "vee-validate/dist/rules";
extend("required", {
...required
});
export default {
data: function() {
return {
username: null
};
},
components: {
ValidationProvider,
ValidationObserver
},
methods: {
sendForm() {
alert(`Thanks ${this.username}`)
}
}
};
</script>
Let's add the method that calls our API. For this example I'll use the Github API to look up usernames. The endpoint URI is https://api.github.com/users/:username
.
Github returns a 404 when the username is not found, in our case that means the field is valid. Whatever your situation is, this method should return true
if valid and false
if not.
export default {
// ...
methods: {
async isUsernameUnique() {
try {
const response = await axios.get(
`https://api.github.com/users/${this.username}`
);
return false;
} catch (err) {
if (err.response.status === 404) {
return true;
}
}
}
}
// ...
}
Now that we have the method in place we can tell VeeValidate to use it in our new rule.
export default {
// ...
mounted() {
extend("unique", {
validate: this.isUsernameUnique,
message: "Username already taken"
});
}
// ...
}
Lastly, we add the rule to the ValidationProvider
.
<ValidationProvider name="username" rules="required|unique" :debounce="500" v-slot="{ errors }">
<p>
<input placeholder="username" v-model="username" type="text">
<br>
<span id="error">{{ errors[0] }}</span>
</p>
</ValidationProvider>
Note that I've added a :debounce
attribute. This ensures we won't be overflowing the API with requests at every keypress but rather every 500ms.
You can find the entire source code for this example on CodeSandbox.
Using handleSubmit
To prevent the user from sending the form before we have heard back from our API we can use handleSubmit
. It takes our own sendForm
method as an argument and using it is very straightforward.
<ValidationObserver v-slot="{ invalid, handleSubmit }">
<!-- the rest of our form -->
<button @click="handleSubmit(sendForm)" :disabled="invalid" type="button">Submit</button>
</ValidationObserver>
Hopefully this simple example will be useful for writing your own server side validation rules.
Posted on February 2, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.