Getting to grips with the jQuery Validation plugin

Introduction

Recently I was assigned the task of adding some validation to a new HTML form. The form itself was nothing out of the ordinary. A standard user registration page like you see everywhere on the web today. The only requirement was that the validation be performed client side. Again, this is what you see on most modern web applications in 2012.

I’m a big believer in reusing existing components, but the trick is to pick the components that are viable to be maintained in the future. Since jQuery was already in use on the project then a jQuery plugin seemed appropriate. jQuery plugins are in abundance on the Internet today, but if I’m going to use something I want it to be maintained and compatible with future versions of jQuery. I knew of the jQuery Validation plugin since I had used it in a previous project. However, I was a little reluctant to jump in with both feet first since I found it a little awkward to work with the last time around. Needless to say, this time it did the job for me, but when trying to get familiar with its usage, good documentation was hard to find.

Now, that’s doesn’t mean that good documentation doesn’t exist, it’s just that a lot of the examples you find on the Internet are either much too simple (and use the simple validation syntax), or they are cluttered with a lot of other unnecessary JavaScript code that overcomplicates the essence of illustrating the validation in action. A good starting point for documentation is the official page from jQuery, but beware, there is so much more to this useful plugin than their examples show you. So let me share my experiences with you here and let you be the judge.

The source code

First things first. All the examples I will be showing you can be downloaded from github. Just head on over to GitHub and download them. There are only five of them and they are very easy to read. You can follow along from the first example and start building a working HTML form.

Create validation for a simple form

When you create an HTML web form you sometimes are a little lenient with the standard attributes used on the input tags – at least I am. It took me a while to figure it out, but the validation plugin won’t work unless the input form tags have a name attribute defined. Take a look at the example below:

<!DOCTYPE html>
<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
        <script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js" type="text/javascript"></script>
        <script src="js/example1.js" type="text/javascript"></script>
    </head>
    <body>
        <form id="validation" action="">
            <fieldset>
                <label id="name-label" for="name">Name:</label>
                <input id="name" name="name" type="text" />
            </fieldset>
            <input id="submit" name="submit" type="submit" value="Validate" />
        </form>
    </body>
</html>
$(document).ready(function () {
    $("form").validate({
        debug: true,
        rules: {
            name: {
                required: true
            }
        }
    });
});

Output of example 1

This is as simple as it gets, but you will see simpler examples than this that make use of the jQuery Validation plugin, most of which use the “easy” configuration syntax adding attributes to the form input fields directly. In my opinion, this approach does not scale and clutters the markup. I prefer a clearer, predictable JavaScript syntax and I don’t mind writing an extra few lines of code to do so. The Validation configuration syntax I’m showing you here is what you should strive for and it will also let your form validation scale. In my experience forms always need to scale so do it right from the start.

This form is easy. It only has one input field. Notice the rules keyword in the validation configuration. Using the input field’s name attribute you define the validation rules for each field. When the user hits the submit button the form will be validated before a POST is attempted. The debug setting is good to have turned on. It will write any errors or warnings to the browsers JavaScript console. It was this helpful setting that made me aware that I was missing the name attribute on my input form fields.

Let’s move on.

Adding more fields

The second example (below) adds a few more fields. You will also notice that I have started to use validation methods here. For instance, now you must type a name of at least 7 characters. The address can be of any length, but it is still required. The zip code must consist of at least 5 digits, and only digits. You can read more about the Validation methods here.

Notice the code for the messages keyword and compare it with rules keyword. You will no doubt see that each validation method has its own custom validation message. I thought that was a pretty nice touch and makes user feedback easy. You don’t have to add your own custom validation messages, but if you don’t then you will get the jQuery Validation plugins own error messages.

Go ahead and run the example in your browser. Use the TAB key to move from field to field. Notice the validation at work when you move from field to field.

<form id="validation" action="">
    <fieldset>
        <div>
            <label id="name-label" for="name">Name:</label>
            <input id="name" name="name" type="text" />
        </div>
        <div>
            <label id="address-label" for="address">Address:</label>
            <input id="address" name="address" type="text" />
        </div>
        <div>
            <label id="zipcode-label" for="zipcode">Zip code:</label>
            <input id="zipcode" name="zipcode" type="text" />
        </div>                
    </fieldset>            
    <input id="submit" name="submit" type="submit" value="Validate" />
</form>
$(document).ready(function () {
    $("form").validate({
        debug: true,
        rules: {
            name: {
                required: true,
                minlength: 7
            },
            address: {
                required: true
            },
            zipcode: {
                required: true,
                digits: true,
                minlength: 5
            }
        },
        messages: {
            name: {
                required: "Required name",
                minlength: "Your name is too short. Must be at least {0} characters."
            },
            address: {
                required: "Required address"
            },
            zipcode: {
                required: "Required zipcode",
                digits: "Only digits accepted",
                minlength: "A minimum of {0} digits are required."
            }
        }
    });
});

Output of example 2

If your input does not validate the error message is displayed at once. You don’t need to submit the form. This a configuration setting that can be easily changed, but I am using the defaults.

The validation error message

You may have noticed that the error message that pops up for the validation is not something that is present in the markup itself. The jQuery Validation plugin is inserting it in to the markup at runtime. In most cases you will want to do something with the presentation of the validation error messages. There are a number of things you can do, but by default the validation plugin encloses the error message in an html label tag with a class named error. It also adds an error class to the input field that failed to validate and a valid class to inputs that are considered valid.
The easy thing to do is to simply create a class for the input and add it to the CSS style sheet. If you run the next example you will see a simple way to style the default error messages. The code is identical to previous example apart from the addition and inclusion of the CSS file. I have also played with the presentation of the error message text and added a valid input style. There are numerous possibilities here including using something other than the html label tag. Check out the errorElement setting in the plugin configuration documentation.

input.valid {
    border: 2px solid green;
}

input.error {
    border: 2px solid red;
}

label.error {
    color: red;
    font-weight: bold;
}

Output of example 3

Giving your use options, but choose at least one

Check boxes are the preferred choice for entering multiple choice input. Validation can be somewhat tricky in this scenario. You can’t simple set a check box validation rule to required since the input is never required. However, sometimes you have to ensure that the user has picked at least one. When reading the documentation to see how this could be done I came across something called grouping, however, I couldn’t get it to work for my scenario. However, I did manage to support this feature by adding a custom validation method and using a hidden form field. The hidden field acts as a place holder to call the custom validation method. It doesn’t really do anything, but the validation uses the jQuery method connected to it to check if a check box is ticked.

Take a look at the next example. Notice the custom validation method at the top, requireOne. It’s purpose is simply to check if one of the check boxes is ticked and then return true or false. However, there is a slight flaw in the plan. Hidden fields are not by default validated by the validation plugin. The call to setDefaults() makes every form element a candidate for validation including hidden fields.

Notice the call to $(“#hiddenOptionValidator”).valid() at the end of the script. I had to add this code to force the plugin to validate the hidden field again once a check box is ticked or unticked. Without this the validation error message for the check boxes will not be cleared until the submit button is pressed which will most likely confuse a user.

<form id="validation" action="">
    <fieldset>
        <div>
            <label id="name-label" for="name">Name:</label>
            <input id="name" name="name" type="text" />
        </div>
        <div>
            <label id="address-label" for="address">Address:</label>
            <input id="address" name="address" type="text" />
        </div>
        <div>
            <label id="zipcode-label" for="zipcode">Zip code:</label>
            <input id="zipcode" name="zipcode" type="text" />
        </div>             
        <div>
            <div>
                <input id="option1" name="option1" type="checkbox" />
                <label for="option1">Option 1</label>
            </div>
            <div>
                <input id="option2" name="option2" type="checkbox" />
                <label for="option2">Option 2</label>
            </div>
            <div>                    
                <input id="option3" name="option3" type="checkbox" />
                <label for="option3">Option 3</label>                            
            </div>
            <div>
                <input id="hiddenOptionValidator" name="hiddenOptionValidator" type="hidden" />
            </div>                    
        </div>
    </fieldset>            
    <input id="submit" name="submit" type="submit" value="Validate" />
</form>
$.validator.addMethod("requireOne",
                        function (value, element) {
                            return $('input[type="checkbox"]:checked').size() > 0;
                        },
                        "Missing required status - Must choose one");

$.validator.setDefaults({ ignore: [] });

$(document).ready(function () {
    $("form").validate({
        debug: true,
        rules: {
            name: {
                required: true,
                minlength: 7
            },
            address: {
                required: true
            },
            zipcode: {
                required: true,
                digits: true,
                minlength: 5
            },
            hiddenOptionValidator: {
                requireOne: true
            }
        },
        messages: {
            name: {
                required: "Required name",
                minlength: "Your name is too short. Must be at least {0} characters."
            },
            address: {
                required: "Required address"
            },
            zipcode: {
                required: "Required zipcode",
                digits: "Only digits accepted",
                minlength: "A minimum of {0} digits are required."
            },
            hiddenOptionValidator: {
                requireOne: "Please tick one checkbox"
            }
        }
    });

    $("input[type='checkbox']").click(function() {
        $("#hiddenOptionValidator").valid();
    });
});

Output of example 4

Validating input based on remote data

Validating input fields is pretty simple, but can quickly elevate up to a something more advanced if you want to do an online lookup for data in a database.

Let’s say you want to register a new user in your system and the unique key is the user’s email address. In most scenarios two users won’t have the same e-mail address since this is unique, but if the same user returns to your registration form and wants to re-register then you have to avoid a new registration and take action before submitting the form. Using the validation email method will handle a user typing a valid e-mail address. Once you are past that hurdle you want to use the remote keyword to look up a backend service to connect to the validation. The documentation is severely lacking here, but luckily it isn’t as hard as it sounds. You do need a backend service to get this working. The thing to remember is that the syntax for the remote keyword configuration is identical to jQuery’s AJAX requests. If you have used AJAX in jQuery before, this should be pretty similar. To set up a backend service is beyond the scope of this article, but take a look at the code example and I’m sure you’ll see what you have to do.

<div>
    <label id="email-label" for="email">E-mail:</label>
    <input id="email" name="email" type="text" />
</div>  
            zipcode: {
                required: true,
                digits: true,
                minlength: 5
            },
            email: {
                required: true,
                email: true,
                remote: {
                    type: "GET",
                    url: "/your-service-url/",
                    cache: false,
                    data: {
                        mail: function () {
                            return $("#mail").val();
                        }
                    },
                    dataType: "json",
                    dataFilter: function (data) {
                        if (data) {
                            var json = $.parseJSON(data);

                            if (json) {
                                return JSON.stringify(json.available);
                            }
                        }

                        return false;
                    }
                }
            },
            hiddenOptionValidator: {
                requireOne: true
            }
        },
        messages: {
            name: {

Output of example 5

Closing

So there you have it! Some simple examples of jQuery Validation plugin usage based on code from the real world. If you are interested in seeing the form on which this posting is based then take a look at this link.
Your feedback, good or bad, is appreciated as always so don’t be afraid to leave a comment. Thanks for reading.