Form Validation with Vue.js

No one likes filling out forms

And it shouldn’t come as a shock. Forms suck and everyone knows it. Filling out a form requires end users to use their brains and recall or create data on the spot. But until we can hook up our brains to the internet, by jamming a big spike into our heads like The Matrix, we are stuck using our perfectly good fingers to input data into little rectangles and hitting the submit button.

We may not be able to get away from using forms as a data collection method, but we can at least make the process a little less painful. One way to do that is to make forms easier for the end user to complete. Properly designing a form and making forms as slim as possible are no-brainers. But what about input validation?

Client-side validation serves many purposes

Maintains data integrity – Your back end usually expects data in a particular shape. Allowing a user to post incomplete or incorrect data can cause unexpected errors in your server code.

Helps guard against malicious users – Validating your inputs before you send them off to your server can help guard against malicious users on the internet who want to commit nefarious deeds against your application. You will notice I say it helps because it really is not a good barrier against most attacks but can help defend against some attacks like SQL injection.

Creates a better user experience – This is probably the best reason to do form validation. When a user enters something into an input field incorrectly, they would rather see a helpful bit of feedback pointing to what caused the error over nothing at all. Not providing useful validation messages can lead to an overall poor user experience.

Ideally, you would have both server side data validation and client side data validation. Don’t forget that client side validation can be completely bypassed and using client side validation only is a BAD IDEA. But I still  recommend using it if for no other reason than to provide a better end user experience.

Lets see some code

I am going to be using bulma and VeeValidate in this example. Below is the markup for a small form with a text, number and email input and the Vue instance that will attach to the ‘app’ div.

In order to start using VeeValidate we need to reference the plugin via the CDN (here) and make sure Vue uses the plugin by adding a Vue.use() statement before our Vue instance is created.


Vue.use(VeeValidate);
var app = new Vue({
    el: "#app",
    data: {
        textField: "",
        numberField: "",
        emailField: ""
    },
    methods: {
        submitForm: function (e) {
            e.preventDefault();
            //post my data to my cool API without any validation! 
        }
    }
});

Next we need to add a directive to the inputs we want to listen to for input errors. Add a v-validate="" directive followed by the rules you want to apply to the input. The directive takes in a | delimited string of all the rules to be used for that input. In my form, I want my number field to be required, only allow a number between 18 and 99 and only allow 2 digits max.

With the directive on the input, VeeValidate attaches a private validator object to the vue instance and exposes a public errors object. To get the error messages generated by VeeValidate, we can use the errors.has(‘fieldName’) method (which returns a boolean) to check if there are any errors associated with the input field in conjunction with Vue’s built in v-show directive to render the error messages for the errors that have been detected. To access the error message itself, we use the errors.first(‘fieldName’) method to retrieve the first error message for that input and output that message in a span. (If you decide to show all errors that have been detected with a particular input, you can use errors.collect(‘fieldName’) to display them)

Now, if the user violates the rules we have imposed on the number field, they will get a handy red message telling them they have made a mistake.

Showing the error is great, but that message is showing the actual field name. Its normal to have a field name that is not display-worthy, but we need to have the field name on the input for VeeValidate to work. Luckily VeeValidate provides us a way to alias a field name and use that in the error message instead. It is the data-vv-as="Friendly field name" attribute.

Now the user sees an easier to understand error message.

One final bit of validation I am going to use happens when the form is submitted. VeeValidate will pick up all the errors a user has generated but it won’t do you any good if the user can still post the bad data. On button click, lets capture the submit event and check for any errors before we allow the data to be submitted. At that point you may want to throw an alert that tells the user they cannot submit the data until the errors have been corrected or highlight the fields again that contain errors.


Vue.use(VeeValidate);
    var app = new Vue({
        el: "#app",
        data: {
            textField: "",
            numberField: "",
            emailField: ""
        },
        methods: {
            submitForm: function (e) {
                e.preventDefault();
                if(this.errors.all().length > 0){
                    //do something to alert the user to the errors
                    return false;
                }
                //post my data to my cool API without any validation! 
            }
        }
    });

And although we have technically created another barrier to entry for our users, it is a necessary one that will make their experience with our products better overall.