Wednesday, October 15, 2008

Starting With jQuery - How to Write Custom Validation Rules

This series of posts on using jQuery with no prior knowledge comes to its fifth iteration. Today, I'm going to look more in depth at the Validation Plug-in.  We'll be looking at what rules the Validation Plug-in comes with out of the box followed by an example of how to create your own rules.   In addition to the typical project that I typically supply, I am also including a list of custom Validations that I have used to hopefully make everyone's life a little easier.
If you would like to review the previous posts in this series, please feel free to review the links below:

Required Downloads to use the Examples:

In order to use the Validation plug-in, you'll need to add a few things to your web page:

Code Downloads for this Post:

Source Code Download: Starting With jQuery - Custom Validation Rules.zip
Just the Rules File: Starting With jQuery - Additional Validation Rules.zip

A Look at some of the Built-In Validation Rules:

A wiser man than I once said that you should strive to never be your own plumber in software development.  Ultimately, you shouldn't spend time writing something that has already been written for you by someone else, is accessible, and meets your needs.  To go along with this concept I think it would be best to briefly cover what rules are already built into this excellent plug in.
  • Required: The typical and probably most used validation out there.
  • Minlength & Maxlength: Staple Length validation rules
  • Rangelength: Similar to Min/Maxlength; allows for selected item counts as well.
  • Min & Max & Range: Same as the "length" rules above only for numeric values.
  • Email: A very robust email validation rule
  • Url: Ensures the input is a well formatted url.
  • Date: Verifies the input can be parsed into a date.
  • Number: Ensures that the input is numeric.
  • Digits: Ensures only 0-9 characters (no commas, decimal points, etc.)
  • Credit Cards: Another complex and common validation rule made easy.
  • Accept: A file extension validation rule.
  • EqualTo: Ensures that the values of 2 elements are the same.
This is just a high level list of what's built in.  For additional information on all of the built in rules and how to use them, head over to the plug-in's documentation pages at http://docs.jquery.com/Plugins/Validation#List_of_built-in_Validation_methods.

Creating a Custom Validation Rule:

Now that we know what's already available, there may come a situation where we find that the built in rules just don't cover everything we need.  When such an occurrence comes upon us, we have the ability to extend the Validation Plug-in.  Custom validation rules are, ultimately, methods that are called and return a boolean value; true if the test succeeds and false if the test fails.  After the methods are created, they can be wired up to the jQuery validation component and used like any other rule.
To create a function that will encapsulate our validation test, we need to use one of the following signatures:
function myTest(value, element){...}
//OR
function mytest(value, element, params){...}
These function signatures, are identical except for the last parameter.  The value parameter houses the value that will be tested.  The element represents the element that is being tested.  The params involves any data that is being passed into the test (i.e. a minimum length value).
Looking over the list of built in validation rules, I noticed that one that was missing was a "Text Only" rule to ensure that only alpha characters would appear in the field.  Using this as an example, our validation rule function would look something like this:
function myTextOnlyValidation(value, element){
    return /[a-zA-Z ]/.test(value);
}

After we have the function established, we can then attach it to the jQuery Validation plug-in.  To do this, we call the validator object's addMethod() function.  This addMethod() function takes 3 parameters; a label for the rule, the function that contains the test, and the default message to display when the test fails. 
$.validator.addMethod("textOnly", myTextOnlyValidation, "Please enter only alpha characters( a-z ).");
Now that the function has been added, we can use the rule, called "textOnly", just like any of the built in rules.

Putting it all Together:

Now that we've looked at the built in rules, created our own rule, and wired up our custom rule; all that's left is to put everything together.  In this example, we're going to keep things simple and use just a single text box, a label, and a submit button (see Figure 1 below).
jQuery5 - Default Form Image
Figure 1 - the default form
For the example, we'll be applying 2 validation rules to this textbox.  The first will be the same required rule that we applied when we were first introduced to the Validation Plug-in.  The second rule will be our custom textOnly rule.  In order to do such, we need to add the following JavaScript to our code:
   1: //Our validation script will go here.
   2: $(document).ready(function(){
   3:  
   4:     //custom validation rule - text only
   5:     $.validator.addMethod("textOnly", 
   6:                           function(value, element) {
   7:                               return !/[0-9]*/.test(value);
   8:                           }, 
   9:                           "Alpha Characters Only."
  10:     );
  11:     
  12:     //validation implementation will go here.
  13:     $("#TestForm").validate({
  14:         rules: {
  15:             txtTextOnly: {
  16:                 required: true,
  17:                 textOnly: true
  18:             }
  19:         },
  20:         messages: {
  21:             txtTextOnly: {
  22:                 required: "* Required"
  23:             }
  24:         }    
  25:     });
  26: })
Note that in the example, the validation function is anonymous inside of the addMethod() function.
After the JavaScript has been applied to the form, we can verify that it works, as shown in Figure 2.
jQuery5 - Text Only Message
Figure 2 - Validating the Custom Rule

Some Additional Custom Rules:

I used the TextOnly rule in the example because it's a rather simple one to illustrate; however, any number of rules can be applied in the same way.  In order to provide additional content and to hopefully give others a jumpstart on implementing the jQuery Validation Plug-in onto their site, I have also added some additional custom rules.  These additional rules, available with in the example site or as a separate download, provide the following functionality:
  • Phone Numbers (in ###-###-#### format)
  • US Postal Codes ( ##### or #####-#### format)
  • Canadian Postal Codes
In addition, I highly encourage anyone interested in writing their own rules to play around and see what you can come up with.  With the power of jQuery, it's possible to pass 2 elements into test functions as parameters to verify something like a mathematical flash card scenario.  In addition, if you are looking for a good Regular Expression repository, I'd highly recommend http://www.regexlib.com for some additional patterns.



UPDATE 25 September 2012:

Since this is one of my most popular posts (THANK YOU!) I decided to address some comments about the example I wrote 4 years ago not working today.  

In terms of the advances of jQuery and the jQuery validation plugin, the code sample will still work properly; however, you'll need to upgrade both of them to the most recent versions (as of this update jQuery 1.8.2 and jQuery Validation 1.9).  Once this is done, the code sample will function continue to function as designed.

There is 1 small bug in the code sample though.  The textOnly rule found in ValidationRules.js and AdditionalRules.js has a bug with the regular expression.  Instead of an asterisk (*) in the regular expression pattern, it should be a plus-sign (+) to signify 1 or more instead of 0 or more.  Correcting this little bug will allow you to use the example rules without an issue.

33 comments:

  1. Awesome article. Thanks! I was able to write a custom validation rule that checks to see if a file has a csv extension. Can you give a quick example code showing how to write a rule that does not use a regex? For example, how can I write a custom rule that checks to see if at least one checkbox in a group is checked?

    ReplyDelete
  2. Ed, there's a built-in rule for validating extensions. I think it's called... "extension".

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Thanks man... Your example of a custom validation rule is very clear and made it quite easy to implement.
    Every other example I saw (looked at about 7-8 pages before I found yours) was way too complex, verbose, cumbersome or something else.
    Thanks for the simplicity and clarity.

    ReplyDelete
  5. Thank you very much for this article on custom jQuery validation. This was the first example I have used that actually worked. Others I have seen leave out code that is essential to the validator working. Much props!!

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. Anybody know how to compare two dates and validate that the first is less than the second, i got a problem with this, i tried validate building date objects, spliting and checking every term(day,month,year), and by any reason i got always true or false, any help?

    ReplyDelete
  8. hi there, i have a question, how can i validate two date inputs on a text input, the second date on the text box should be a higher date. i need to doit with validation.js can you helpme

    ReplyDelete
  9. Thanks for the tutorial. Very simple and easy to read and impliment. Only one question. How to color code the error messages something other than default black?

    ReplyDelete
  10. @John

    Hi John,

    To answer your question about changing the color of the error message, the Validation plug-in sets a css class on the error text. In order to change the color, all you have to do is add a CSS definition for the "error" class. This should take of it for you.

    Hope this helps.

    ReplyDelete
  11. Hi James,

    Great blog post! I was looking everywhere for an easy to understand implementation of custom rules and yours was the best i found!

    I got yours working but I'm having a little trouble implementing my own rule....

    $.validator.addMethod("validTotalValue",
    function(value) {
    var outcome = parseInt($("#valuePerNight").val()) * parseInt($("#numberOfNights").val()) + parseInt($("#otherCharges").val()) != parseInt($("#totalValue").val())
    alert("outcome:" + outcome)
    return outcome;
    },
    "enter a valid totalValue"
    );

    I tested the logic and it works (outputs true/flase) I'm just not sure why its not hooking up and it doesn't highlight the error?

    ReplyDelete
    Replies
    1. You have to use your method as a rule when you call .validate()

      Delete
  12. Thanks a ton it was a wonderful help, now to write custom validation rules is simple and easy by using your advice. Thanks

    ReplyDelete
  13. Excellent introduction to customize jquery validator plugin.

    ReplyDelete
  14. Nice Article. 100% Helpful and success effort. A+++++++

    ReplyDelete
  15. i run the code above, but didn't work, am i lacking something?

    ReplyDelete
  16. @marjune I just tested by pulling down the "Starting with jQuery - Validation Rules" zip file, opened default.htm in a browser (Chrome 21) and it worked properly. The example was written 4 years ago so I cannot guarantee that it works flawlessly with the most recent versions of jQuery and the jQuery validation plugin.

    ReplyDelete
  17. @marjune I reviewed the code and was able to get it to function 100% with the latest versions of jQuery (1.8.2) and the jQuery validation plugin (1.9). I had to update both of them, though. I also found a bug with the textOnly rule which I have commented on in an update I have made to the blog post.

    If you are still having issues, please let me know and we'll figure out how to work through it offline perhaps.

    ReplyDelete
  18. Thanks for this tutorial

    ReplyDelete
  19. This was very helpful! Many thanks!

    ReplyDelete
  20. Awesome article, thanks a lot...

    ReplyDelete
  21. Hi James Eggers,

    Im neal.

    How will I validate if i want that users will not enter zero.

    ReplyDelete
  22. nice article ..

    Hi James Eggers,

    is this possible if i want to have two or more textfield with same rules and message, but have different name of each textfield, or i must write rules and message of each textfield, thanks.

    ReplyDelete
    Replies
    1. For each field, you'd need to list them separately in the rules section of the validation configuration.

      For example
      $("#TestForm").validate({
      rules: {
      txtTextOnly: {required: true,textOnly: true},
      txtTextOnly2: {required: true,textOnly: true}
      },
      messages: {
      txtTextOnly: {required: "* Required"},
      txtTextOnly2: {required: "* Required"}
      }
      });

      Hope this helps

      Delete
  23. Thanks - a big help. It's a shame the author of the plugin wasn't as clear and as comprehensive as you have been.

    ReplyDelete
  24. what if i have to check all the fields at once.
    I dont want to write this long code

    ReplyDelete
  25. Great post! Couldn't figure it out from the JQuery docs - Thanks!

    ReplyDelete
  26. Thanks! Great Post - very clear as usual

    ReplyDelete