Why Vuetify’s native form validation sucks
Introduction
Form validation is the crucial part of any web application. The users won’t always know how to fill your form and most of them will need a guidance. Thus, it’s crucial for us — front end developers — to define visually (and semantically) which inputs are required, and what kind of data the user needs to fill in. For this purpose, we may use native HTML5 form validation or some library to do more advanced and visually appealing form validations. In this article we’re going to talk about Vuetify’s form validation, what it lacks and why you might wanna use third party library instead of using rules
prop.
Form validation with Vuetify
Vuetify is popular UI library for Vue that implements material design. It has plenty of components, utility classes and themes that may be handy if you want to build web applications in short time slot without worrying about cross-browser compatibility and performance. Let’s look at how we can use Vuetify to validate a form.
If we look at the docs about form validation we’ll see three options. Two of the options tell us to use vee-validate and vuelidate libraries and the first one shows us how we can use rules
prop to validate the form.
Let’s say I do not want to use third party library to keep my app’s bundle size small or for some other reason. For that, I should add rules
prop to the form element which is just an array of functions that return either true
or some string value (error message). Here is how it looks like:
To trigger the validation and check if the form is valid, we need to use methods that v-form
has. According to the docs, validate
method validates all registered inputs and returns true
if validation was successful and false
otherwise. Following the docs, the handleSubmit
method would look like this:
Now, this process is quite straightforward, we can look at what the problem is.
The problem
Let’s say we want to add another input, which requires validation with external API. If you dig into the documentation, you’ll find out that there is no way to use async
function for the rules
prop. So, if you imagined something like below, this is not going to work:
The only way to validate form element with an API is to use error
, error-messages
and error-count
props. These props just set the validation state of the form element:
To test this, lets’s add the second input with error-messages
into the form:
Now what happens if we hit submit button? Go to the sandbox I have created, click the submit button and look at the console. Although we have marked the second input as invalid, this.$refs.form.validate()
will return true
. This is not an expected behavior in both from developer perspective and from user perspective. In this case, the API request will still be made even though the surname
input is invalid (a.k.a has error-messages
). So what is the cause of this problem?
The cause
To see the reason behind this logic, let’s dive into Vuetify’s source code. Let’s start from VForm component and see how validate
method works:
Validate method takes all the inputs the form has, calls validate method on them and filters them to find if there is an invalid input or not. If you look at the VTextField component, you will see that there isn’t any method named validate
. This is because all form elements implement validatable mixin which has all the properties and methods that a validatable form element has. Let’s look inside of validatable mixin and see what validate
method does:
As you see, it calls all the functions that the rules
prop has, pushes the error messages (if there are any) into the variable called errorBucket
and finally checks if error bucket is empty or not. If empty then this input element is valid. The error-messages
prop that we passed to our second element is accepted as a prop and is not being checked inside validate
method. So the error-messages
prop is for visual purpose only.
The solution
Possible solutions for the case above would be to use async
for loop to be able to run rules that contain async
functions or check the errorMessages
props along with errorBucket
or copy the errorMessages
prop to errorBucket
variable on mount
.
I have opened an issue on this one and it was closed saying that this is not a feature they want to implement for now 🐵.
Conclusion
Take home lesson from this article would be — Do not rely on Vuetify’s native form validation. If you will need some extended functionality on validation (like API validation) use libraries like vee-validate
or vuelidate
.
Thanks for reading and do not hesitate to reach me out or comment below, if you think I am missing something or you have an alternative approach to solve this issue.