September 26, 2009

jQuery, me and form validation

Whether they know it or not anyone that has used the internet has experienced form or content validation. The purpose of content validation is to preserve the integrity of the application or service. Entering “100” as your first name wouldn’t make much sense. Trying to email “ABC-123?” wouldn’t make sense either. To prevent this from happening we can validate content in all sorts of ways, but the most important thing to remember is define what you will allow and not what you wont. For the examples to come I’ll be using the lovely Mary Jane Watson.

On the web there are two locations were validation can happen, on the server or in the browser. The application receives the content and validates it to determine whether to perform the next action or not. This is server-side validation. There is also client-side validation, handled by the browser. This is approach is done with JavaScript. Server-side validation is required, but client-side validation isn’t. Even though client-side validation isn’t required I can think of more reasons to do it than not. From a usability standpoint client-side validation is excellent. The user should receive feedback indicating whether or not content entered is allowed. Twitter does this with their sign up form as you type. Facebook gives feedback after you hit submit. Both are acceptable approaches. It also reduces the load on your server. By checking the user’s content before sending it to the server reduces the amount of work your server has to do. This is great because the server can spend those unused resources elsewhere. So now that we’ve seen two real world examples and understand the server benefits let’s get started validating with JavaScript.

Validating With Regular Expressions

A first name field should accept A-Z characters, both capitalized and lowercase. In Mary Jane’s case she has a space in her name. We’ll need to account for that too. We don’t want numbers or symbols, but as I wrote previously, only define what you will allow. It’s time for regular expressions. If you aren’t familiar with regular expressions you can check out O’Reilly’s Mastering Regular Expressions or you’ll appreciate this article that much more.

To indicate that we’re looking for A-Z characters we can use just that, /[A-Z]/, but we need to allow both upper and lowercase. That can be done by defining a-z as well, /[A-Za-z]/, or appending i to our regular expression, /[A-Z]/i. Regular expressions aren’t the easiest things to read so pick whichever make sense to you. We also want to allow spaces, since “Mary Jane” contains a space. This can be done with \s or \ . The second option is a back slashed space. Now our regular expression looks like /[A-Z\s]/i. That will match any of those characters, but we haven’t said that we only want those characters. Now for the fun stuff. The carrot(^) indicates the beginning of a line. The dollar sign($) indicates the end of a line. The asterisk(*) allows for zero or more characters. The plus sign(+) allows for one or more characters. So putting them together gives us /^[A-Z\s]+$/i. This regular expression will accept “Mary Jane” as a first name.

We’ve just structured our regular expression so now we’ll need to use it. We can validate the first name field on one or many events. Since we’re using jQuery we can write a blur event like this:

1
2
3
4
5
6
7
$('input[name=first_name]').blur(function(){
  var $input = $(this); // define the input object with jQuery
  if(this.value.match(/^[A-Z\s]+$/i))
    $input.removeClass('error'); // an example of removing the class error from the input field
  else
    $input.addClass('error'); // adding the error class if invalid content is entered
});

Lets write another example, but a little more in depth.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var regex = {
  first_name: /^[A-Z\s]+$/i,
  last_name: /^[A-Z\s]+$/i,
  age: /^[0-9]{1,3}/,
  zip_code: /^[0-9]{5}$/,
};

for(name in regex)
{
  $('input[name='+name+']').blur(function(){
    var $input = $(this); // define the input object with jQuery
    if(this.value.match(/^[A-Z\s]+$/i))
      $input.removeClass('error');
    else
      $input.addClass('error');
  });
}

Our code isn’t too long yet, but thats just three fields and their all input fields. We’re keeping this post relatively simple so we wont be checking any select menus, text areas, check boxes or radio buttons.

Simplifying Form Validation With validate_me

Like the README of the validate_me plugin states, “I hate doing form validation.” We know why we should do it, but that still doesn’t make me enjoy it. I decided to fix my problem by creating a simple approach to validating form content. This is where jQuery really comes in. I created a jQuery plugin I’m called validate_me which mimics Ruby on Rails model validators. Let’s attempt the same type of validation from earlier, but using validate_me.

1
2
3
4
5
6
7
8
9
$.validates_presence_of('first_name', 'last_name', 'age', 'zip_code'); // this states that all of these elements must have a value

$. validates_format_of('first_name', { on: 'blur', with: /^[A-Z\s]+$/i }); // we still have to use a regular expression for this case
$. validates_format_of('last_name', { on: 'blur', with: /^[A-Z\s]+$/i }); // and this case

$.validates_numericality_of('age', { on: 'blur', greater_than: 0 }); // we don't want someone to be zero do we?

$.validates_numericality_of('zip_code', { on: 'blur', greater_than: 0 }); // a zip code can't be zero
$.validates_length_of('zip_code', { on: 'blur', is: 5 }); // and it needs to be five digits

Well that was easy! It’s very readable too. Let’s tweak our code to validate the content as the user enters it. That way they’ll know the instant they make a mistake. To do this we should validate the content on the blur event as well as the keyup event.


$. validates_format_of('first_name', { on: ['blur','keyup'], with: /^[A-Z\s]+$/i });

Notice the on value is now an array appose to a string from earlier. Each field is validated automatically when the form is submitted so adding “submit” to the on values isn’t necessary.

That’s simplified form validation in a nutshell. The full list of validation methods and their arguments are available at the Github repository.

I hope this is helpful!

Note: The URL’s were updated to point to the renamed repository.

Leave a Comment


Please wait...