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.

Advertisements

Using Fiddler as a simple http development server

Fiddler’s AutoResponder

Lately I’ve been playing around with Fiddler (version 2.3.4.4). Fiddler it is a free packet analyzer for web debugging HTTP and HTTPS traffic. It acts as a proxy between your web browser and a web server so you direct your web browser to it using a plugin (for Firefox) and it enables you to analyze and tamper with the HTTP requests and responses between the server and client. Very cool and very useful.

Screenshot of Fiddler user interface

Although Fiddler is packed with lots of useful functionality for analyzing and tampering with HTTP traffic I also found a new use for it when working with jQuery and JSON.

Just recently I was looking in to the jQuery UI Autocomplete plugin and wanted to play around with the functionality that uses JSON returned from the server. To simplify, my idea was to test the Javascript client code without writing any server-side code. Of course I could have simulated something similar by creating JSON in the Javascript code, but that’s not what I wanted here since I it was important to get familiar with the code making the JSON request over the wire. The client code that I ended up creating with can easily be deployed to a proper web server without modification.

Fiddler’s AutoResponder functionality

Fiddler includes something called AutoResponder. As the name gives away, you use it to automatically send a response to a calling browser client. The idea is to get Fiddler to intervene and return something useful when the browser makes a request for a particular URI. In my case I was aiming at making Fiddler return static JSON to the browser when making a call to http://server.anywhere.com/json. I created the contents of a HTTP response that I wanted to be returned to the browser in a file and stored it to disk. Then I redirected the AutoResponder to return this file when the browser request was made. I made no modifications to my hosts file.

Screenshot of the configured AutoResponder in Fiddler

Very simple really. As you can see from the screenshot above. I have configured two URIs. One is for the index.html file and the other for the JSON “service”. When one of the URIs is hit by the browser the corresponding file on the file system will be returned. The AutoResponder also lets me set latency so I simulated a 3000 ms sleep for the service before responding.

The tricky part was actually making a valid HTTP file for the JSON service. In my case it looked as shown below and saved as UTF-8. For this purpose I found Notepad++ to be very useful. When selecting the actual HTTP content text in the file it tells you exactly how many bytes are needed as value for the content length header. In my case it was 87 bytes.

A screenshot of calculating the number of bytes in the html response with Notepad++

Now, when opening the browser and making a call to http://server.anywhere.com/json the AutoResponder will step in and return the JSON to the browser. The code I used for invoking the call to return the JSON is shown below. Of course this code ignores what is typed in the input field and results the same JSON regardless, but for my purpose that’s okay.

<html>
    <head>
        <title>jQuery Autocompletion with JSON call</title>
        
        <link rel="stylesheet" 
              type="text/css" 
              href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.5/themes/ui-lightness/jquery-ui.css" />

        <script type="text/javascript" 
                src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
              
        <script type="text/javascript" 
                src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.5/jquery-ui.min.js"></script>
        
        <script type="text/javascript">
            $(document).ready(function() {
                $( "#tags" ).autocomplete({
                    source: function(request, response) {                                               
                        var url = "json";
                        var param = "";
     
                        $.getJSON(url, param, function(data) {
                            response(data);
                        });
                    }
                });
            });
            </script>        
    </head>

    <body>
        <div class="demo">
            <div class="ui-widget">
                <label for="tags">Tags: </label>
                <input id="tags" />
            </div>
        </div>
    </body>
</html>

Same origin policy

When requesting data using Javascript there are some security limitations that the browser enforces, one being the same origin policy. This policy restricts Javascript from accessing JSON from a different domain than the one hosting the script making the call. So if I want to request JSON from http://server.anywhere.com/json then the Javascript which makes the JSON call needs to originate from the same domain, http://server.anywhere.com/.

Again, AutoResponder to the rescue. I set up the AutoResponder to call my html page (the file which includes my Javascript) and mapped this file to a known URI from the same domain as the simulated JSON service. When the browser makes the initial request to http://server.anywhere.com/index.html, Fiddler’s AutoResponder intercepts the request and redirects a file from my local drive to the browser. The browser thinks it’s getting files from the web, but in fact Fiddler is just redirecting files from my local hard drive. When the time comes to trigger the script requesting the JSON from the simulate service at http://server.anywhere.com/json the AutoResponder steps in and returns my static JSON file. Notice the host name in the screen shot below and the jQuery autocomplete plugin in action.

Screenshot of the resultsing page in browser

Maybe a little clumsy to set up, but once done you can tweak everything in the files and no need to deploy any code or install any servers. I thought it was a nice touch that the AutoResponder can simulate latency so you can test any timeout functionality on the client side without having to add thread sleeps which usually is the case for service development.

Conclusion

I am really happy with Fiddler. I have used WireShark in the past, but for working with HTTP traffic it is a little too heavy. Fiddler has a lot of interesting features for web development and analysis work.