Monday, May 5, 2008

jQuery Plugin Validation with AJAX

posted by Alex Grande
The JQuery plugin Validation by bassistance.de is extension, powerful, and quick-to-deploy. I recommend this library for people already using the jQ framework to provide high-quality, usable client-side form validation. We are going to discuss basic properties of this framework as well as AJAX and scalability. Here is the code we are going to step through. This code was specifically designed to create an ajax experience for the medical technology company eMedTV.com. The live example can be found at this address. Here's my validation function:
$(document).ready(function() {
    if (pageName=="researchCenter") {
// Just use a different variable for each form you use. It is too difficult to use just one for all forms because each form has it's own plethora of needs (usually).
    var validator = $("#researchCenterForm").validate({
// #messageBox holds the all encompassing message at the top to let all the users know  there is a problem.
         errorContainer:"#messageBox",
// This is very important for manipulating the placement and styles of the error message for individual cases, such as first name or zip. I'll explain this later.
         errorClass: "formError",
// wrapper is only needed if you want to wrap the error message in something. If you  want a list the errors it can be a 
  • . I didn't really find any need for this unless you were listing all the errors at the top. wrapper: null, // errorPlacement is very important. It is where in the DOM you want the error of each idividual case to appear. I wanted each error to be placed at the beginning of each form element list item. See HTML example below. errorPlacement: function(error, element) { error.insertBefore(element); }, // On to the rules and without this the form wouldn't be what it is! rules: { // All the methods are found as having the name's inside the form. Thus in order for email to work I have to have a form element with name="email". zip: { // required:true is a must if you want the validator to check this element. required:true, // digits is one of the mime types of only digits. You put in alpha characters and it lets you know it doesn't like that! digits: true, minlength: 5, maxlength: 5 }, betterEmail: { required: true, email: true }, // If you have a confirm or email again area then we have some special rules to make sure this works. confirmEmail: { required: true, // #email is the id of the first email. For example, equalTo: "#email", email: true } required:true } }, //Here are all the messages for the different errors on the page. This is OOP so the method (firstname:) must match the ID of the required field. If it is not required it will not receive an error message. messages: { firstname: "Please enter your first name.", lastname: "Please enter your last name.", username: { required: "Please enter a username.", minLength: "Your username must consist of at least 2 characters." }, password: { required: "Please provide a password.", minLength: "Your password must be at least 5 characters long." }, confirmPassword: { required: "Please provide a password.", minLength: "Your password must be at least 5 characters long.", equalTo: "Please enter the same password as above." }, email: "Please enter a valid email address.", confirmEmail: "Please enter the same email.", zip: "Please enter a valid zip code.", agreeToService: "Please check the box." }, // Here is the fun part and the tricky part: AJAX // SubmitHandler is called when the form is called. When the users clicks submit on your form this is what happens. Since we want to do ajax you use the $.ajax jQ object. It has to start with function() {} for it to work. submitHandler: function() { $.ajax({ See serialize here http://docs.jquery.com/Ajax/serialize data:$("#researchCenterForm").serialize(), // The url you are going to submit to url: submit.php, timeout: 2000, // Sends a message to the console if it failed for testing purposes. error: function() { console.log("Failed to submit"); }, // If successful you can do something here. You can change elements, update text, or simply alert the response to first test to see if it worked. success: function(response) { alert(response); } }); } }) } });
  • First thing you'll probably notice is this plugin is formatted in object oriented programming. So it is very straight forward to know which methods and which properties to use for your form. Once you locate the ultimate guide to how to use the validator, it can become relatively straight forward to use. How to stylize where error label fields go on the page CSS:
    .formError {
            position: absolute;
            margin: 21px -13pt 0pt;
    }
    li {
            position: relative;
    }
    
    The margin is to position the error label below the form field, such as an email input box. Positioning it absolutely makes sure the forms look and feel is not altered by static elements. HTML:
    You'll notice the class name "betterEmail" and "required". This is to enter in jQ validation methods into the html markup itself. Cool huh? The HTML after the error has been applied in real-time:
    Once you have your form all setup you can start writing your own mime types if you include the mime type plugin as well. Currently the validator checks if your email is alex@alexgrande and that's it. If you want to make sure there is a .com or .org, etc you need this:
    jQuery.validator.addMethod("betterEmail", function(value, element) {
     return this.optional(element) || /^[^\x00-\x20()<>@,;:\\".[\]\x7f-\xff]+(?:\.[^\x00-\x20()<>@,;:\\".[\]\x7f-\xff]+)*\@[^\x00-\x20()<>@,;:\\".[\]\x7f-\xff]+(?:\.[^\x00-\x20()<>@,;:\\".[\]\x7f-\xff]+)+$/i.test(value);
    }, "Valid Email Please"); 
    
    See I how I use betterEmail above. Another is if you have a drop down menu like a select box with options. There isn't a default way to do this. My solution is the following. Notice the option with the value="none".
    jQuery.validator.addMethod("selectCountry", function(value, element) {
     return this.optional(element) || ( value.indexOf("none") == -1);
    }, "Please choose a Country."); 
    
    
    
    Another problem I have found is if you have three different select boxes, such as month, day, and year and you want only one error message for all three since they are all related. My solution is to make all three error message overlap making it appear they are all the same to the user. HTML:
  • What is your (or the participant) date of birth?

  • CSS:
    li#date .formError {
     left: 2px;
     bottom: -15px;
    }
    
    Thus every formError will overlap each other with the same position on the page. Last problem is fixing error form position issues in IE. That's easy. If you read my article about handling cross-browser issues then you'll know most of what to do. Since we positioned the error message absolutely we can position it using IE conditional comments only for IE. CSS:
    .ie li#date .formError {
     top: 1000px;
    }
    
    This is all for this discussion. If I think of more I'll add to it later. In either case, please send questions or comments.

    Labels: , ,

    2 Comments:

    Blogger Unknown said...

    The email validation got fixed in the 1.2.1 release, it now requires the .xxx part. So your betterEmail-method isn't necessary anymore.

    Your select method can be replaced by using a required rule with value="". That is, replace "none" with an empty string.

    The 1.3 release added a "groups" option. In your date-example, you specify this:

    groups: { dateGroup: "DOBMonth DOBDay DOBYear" }

    Depending on your layout, you still need to specify the message placement using the errorPlacement-option.

    I hope that helps. Let me know if you find other issues, I'm sure we can solve those, too.

    May 25, 2008 at 5:46 AM  
    Anonymous Anonymous said...

    Congratulations guy!
    It helped me a lot !
    Made me not wast time on my own function to do that.
    I really apreciate your help.
    Thank u a lot !

    July 2, 2008 at 1:40 PM  

    Post a Comment

    Subscribe to Post Comments [Atom]

    << Home