Search

Using Ajax to Validate Forms

Posted on 18th December 2007 — Forms are such a common element on the Internet we tend to blunder through them without too much thought. However, if the web site has added a few nice touches that make the process easier, it tends to speed up the process and reduce any frustration in finding our preferred username (i.e. try getting your name under Hotmail!).

There’s two types of validation:

  1. Simple, server-independent validation, i.e. checking email address are the right format, password and confirm password matches, etc.
  2. Server-based validation, with can be delivered with a page refresh, or live (as this tutorial will explain), i.e. for checking whether a username is taken.

What can we do?

  • Live username checking
  • Password confirmation and strength
  • Checking if an email address is already registered
  • URL validation, i.e. Basecamp’s site address checks if the URL is available (pretty much the same as username validation)

So why do it?

  • It makes the user’s experience quicker, or arguably better
  • It’s not much extra work to put in place (explained below)

Examples in the wild

Howto

As with all these tutorials, I expect that you have built your solution to the point where it works, but now we want to add our splash of JavaScript magic.

In our baseline example, my requirements are:

  • Username validation kept in separate function
  • Server side does the it’s normal job
  • I can detect an Ajax request and return something different

Username validation

Our PHP function to validate the username reads:

function check_username($username) {
  $username = trim($username); // strip any white space
  $response = array(); // our response
  
  // if the username is blank
  if (!$username) {
    $response = array(
      'ok' => false, 
      'msg' => "Please specify a username");
      
  // if the username does not match a-z or '.', '-', '_' then it's not valid
  } else if (!preg_match('/^[a-z0-9.-_]+$/', $username)) {
    $response = array(
      'ok' => false, 
      'msg' => "Your username can only contain alphanumerics and period, dash and underscore (.-_)");
      
  // this would live in an external library just to check if the username is taken
  } else if (username_taken($username)) {
    $response = array(
      'ok' => false, 
      'msg' => "The selected username is not available");
      
  // it's all good
  } else {
    $response = array(
      'ok' => true, 
      'msg' => "This username is free");
  }

  return $response;        
}

This format for a response is good, because we are using it to display error messages on the page, but we can also convert it to JSON and use it in our Ajax response later on.

Markup

Again, it’s assumed your markup is already designed to show error messages.

For this example the following markup is being used within a fieldset:

<div>
    <label for="username">Username, valid: a-z.-_</label>
    <input type="text" name="username" value="<?=@$_REQUEST['username']?>" id="username" />
    <span id="validateUsername"><?php if ($error) { echo $error['msg']; } ?></span>
</div>

jQuery

Our client side check will perform the following:

  1. Only if the value has changed run the check, i.e. ignore meta keys
  2. Use a nice ajax spinner to indicate activity
  3. Make an Ajax request and show the response
$(document).ready(function () {
  var validateUsername = $('#validateUsername');
  $('#username').keyup(function () {
    var t = this; 
    if (this.value != this.lastValue) {
      if (this.timer) clearTimeout(this.timer);
      validateUsername.removeClass('error').html('<img src="images/ajax-loader.gif" height="16" width="16" /> checking availability...');
      
      this.timer = setTimeout(function () {
        $.ajax({
          url: 'ajax-validation.php',
          data: 'action=check_username&username=' + t.value,
          dataType: 'json',
          type: 'post',
          success: function (j) {
            validateUsername.html(j.msg);
          }
        });
      }, 200);
      
      this.lastValue = this.value;
    }
  });
});

The code breaks down as follows:

$(document).ready(function () {

Run the JavaScript in this (anonymous) function when the document has loaded.

var validateUsername = $('#validateUsername');

Create a cached copy of the validateUsername span because it will help a little with optimisation (it’s a good practise to have).

$('#username').keyup(function () {

Run the JavaScript in this (anonymous) function on key up.

var t = this;

Cache the ‘this’ instance as we need access to it within a setTimeout, where ‘this’ is set to ‘window’, which can cause all manners of confusion.

if (this.value != this.lastValue) {

Only run the check if the username has actually changed - also means we skip meta keys.

if (this.timer) clearTimeout(this.timer);

The timeout logic means the ajax doesn’t fire with every key press, i.e. if the user holds down a particular key, it will only fire when the release the key.

validateUsername.removeClass('error').html('<img src="images/ajax-loader.gif" height="16" width="16" /> checking availability...');

Show our holding text in the validation message space.

this.timer = setTimeout(function () {

Fire an ajax request in 1/5 of a second.

$.ajax({
  url: 'ajax-validation.php',
  data: 'action=check_username&username=' + t.value,
  dataType: 'json',
  type: 'post',
  success: function (j) {
    validateUsername.html(j.msg);
  }
});

The actual Ajax request. If the script ajax-validation.php returns any response, convert it to JSON and put the ‘msg’ field in to the validation message.

The fields are set in the PHP server response. You can see this working in the demo, and view the source, in particular look at the $resp array from check_username.

this.lastValue = this.value;

Finally, put the current value in to a cache, to make sure we ignore meta keys (from above).

Server response

Now all I have to add to the PHP code, that already handles normal username validation is:

if (@$_REQUEST['action'] == 'check_username' && isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
    echo json_encode(check_username($_REQUEST['username']));
    exit; // only print out the json version of the response
}

So long as this is high enough in the logic, it will just check the username is valid, using our existing function and convert the response to a JSON object (you may need to add JSON support for PHP, otherwise it’s bundled with PHP 5.2.0).

Example & taking it further

In the example I’ve provided, I’ve also shown how we can add JavaScript to a normally coded page to also validate the user providing an avatar URL.

Related posts

Demo

If you find this demo doesn't work as expected, it's possibly due to the demo running from within an iframe. Try running the demo in it's own window.

Source Code

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en">
  <head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <title>jQuery for Designers - Ajax Form Validation Example</title>
    <style type="text/css" media="screen">
    <!--
      BODY { margin: 10px; padding: 0; font: 1em "Trebuchet MS", verdana, arial, sans-serif; font-size: 100%; }
      H1 { margin-bottom: 2px; font-family: Garamond, "Times New Roman", Times, Serif;}
      TEXTAREA { width: 80%;}
      FIELDSET { border: 1px solid #ccc; padding: 1em; margin: 0; }
      LEGEND { color: #ccc; font-size: 120%; }
      INPUT, TEXTAREA { font-family: Arial, verdana; font-size: 125%; padding: 7px; }
      LABEL { display: block; margin-top: 10px; } 
      IMG { margin: 5px; }
      #message {
          border: 1px solid #ccc;
          background-color: #ffa;
          padding: 5px;
      }
      DIV.submit {
        background: #eee;
        border: 1px solid #ccc;
        border-top: 0;
        padding: 1em;
        text-align: right;
        margin-bottom: 20px;
      }
      IMG.avatar {
          vertical-align: top;
      }
    -->
    </style>

    <script src="jquery.js" type="text/javascript"></script>
    <script type="text/javascript">
    <!--
    $(document).ready(function () {
        // Username validation logic
        var validateUsername = $('#validateUsername');
        $('#username').keyup(function () {
            // cache the 'this' instance as we need access to it within a setTimeout, where 'this' is set to 'window'
            var t = this; 
            
            // only run the check if the username has actually changed - also means we skip meta keys
            if (this.value != this.lastValue) {
                
                // the timeout logic means the ajax doesn't fire with *every* key press, i.e. if the user holds down
                // a particular key, it will only fire when the release the key.
                                
                if (this.timer) clearTimeout(this.timer);
                
                // show our holding text in the validation message space
                validateUsername.removeClass('error').html('<img src="images/ajax-loader.gif" height="16" width="16" /> checking availability...');
                
                // fire an ajax request in 1/5 of a second
                this.timer = setTimeout(function () {
                    $.ajax({
                        url: 'ajax-validation.php',
                        data: 'action=check_username&username=' + t.value,
                        dataType: 'json',
                        type: 'post',
                        success: function (j) {
                            // put the 'msg' field from the $resp array from check_username (php code) in to the validation message
                            validateUsername.html(j.msg);
                        }
                    });
                }, 200);
                
                // copy the latest value to avoid sending requests when we don't need to
                this.lastValue = this.value;
            }
        });
        
        // avatar validation
        // we use keyup *and* change because 
        $('#avatar').keyup(function () {
            var t = this;
            clearTimeout(this.timer);
            this.timer = setTimeout(function () {
                if (t.value == t.current) {
                    return true;
                }

                var preview = $('#validateAvatar').html('<img src="images/ajax-loader.gif" height="16" width="16" /> trying to load avatar...');
                var i = new Image();

                clearTimeout(t.timeout);

                if (t.value == '') {
                    preview.html('');
                } else {
                    i.src = t.value;
                    i.height = 32;
                    i.width = 32;
                    i.className = 'avatar';

                    // set a timeout of x seconds to load the image, otherwise, show the fail message
                    t.timeout = setTimeout(function () {
                        preview.html('Image could not be loaded.');
                        i = null;
                    }, 3000);

                    // if the dummy image holder loads, we'll show the image in the validation space,
                    // but importantly, we clear the timer set above
                    i.onload = function () {
                        clearTimeout(t.timeout);
                        preview.empty().append(i);
                        i = null;
                    };
                }
                
                t.current = t.value;
            }, 250);
        }).change(function () {
            $(this).keyup(); // call the keyup function
        });
    });
    //-->
    </script>
  </head>
  <body>
    <div>
        <h1>jQuery for Designers - Ajax Form Validation Example</h1>
        <p>This shows two examples of client side validation in a form using JavaScript (with jQuery). The username will check with the server whether the chosen name is a) valid and b) available. The avatar example tries to load the URL in to a hidden image, if it fails, it shows the appropriate message.</p>
        <p><a href="http://jqueryfordesigners.com/using-ajax-to-validate-forms/">Read the article this demonstration relates to</a></p>
        <p><a href="?action=register&amp;username=remy&amp;avatar=http://tbn0.google.com/images?q=tbn:gLMWxXGcr71JVM">Example of failing username and successful avatar</a></p>
        <p><a href="?nojs">See the non-JavaScript version</a></p>
        <form action="" method="post">
            <fieldset>
                <legend>Register</legend>
                <div>
                    <label for="username">Username, valid: a-z.-_</label>
                    <input type="text" name="username" value="" id="username" />
                    <span id="validateUsername"></span>
                </div>
                <div>
                    <label for="avatar">Avatar URL</label>
                    <input type="text" name="avatar" size="50" value="" id="avatar" />
                    <span id="validateAvatar"></span>
                </div>
            </fieldset>
            <input type="hidden" name="action" value="register" />
            <div class="submit"><input type="submit" name="register" value="Register" id="register" /></div>
        </form>
        <p>Note that the following usernames are permanently unavailable for the purpose of this demo: remy, julie, andrew, andy, simon, chris, nick</p>
    </div>
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-1656750-8";
urchinTracker();
</script>
  </body>
</html>

Comments

  1. Andreas On 3rd January 2008 at 14:01

    This is perfik, I’ve been thinking about how to solve a couple of issues with my “live search” on my site, but your use of setTimeout and checking the last value are so simple and logical. Exactly what I needed. Cheers.

  2. Chris Mahon On 4th January 2008 at 11:01

    Hi Remy,

    Great article. I just wondered what the $_REQUEST variable was used for in PHP? Is this like $_GET and $_POST all in one and if so, is it not better to check only for the type of request you are expecting? I.E. not allowing people to pass variables through the URL?

  3. Remy On 4th January 2008 at 12:01

    @Chris - absolutely correct. If you wanted to restrict which method you read from, you could specify $_POST or otherwise. Remember that it’s easy for someone to tweak the posting method if they really wanted to though.

  4. JL On 2nd February 2008 at 22:02

    Great, but how can i check a mysql database and create a $taken_usernames array? ps: i am a beginner.

  5. James On 15th March 2008 at 16:03

    Remy, excellent article! This has helped me a great deal when learning jQuery AJAX. I do have one small suggestion to make; When entering a username, it’s better practice to restrict the length of the uname then fire off a Ajax call thus minimizing php/db processing. E.g. if (this.val().length <= 5) { return false }. Other than that, great job!

  6. Chris On 21st March 2008 at 15:03

    Remy,

    Got a quick question for you regarding validation on forms. Basically I want to change the value and disable a submit button once clicked on to ensure the user knows something is happening (my server is a bit slow!!) but using the following code, it changes the submit button’s value/disables it but the form doesn’t submit…

    $("input[@type='submit']").submitcheck();
    
    // Check submit
    jQuery.fn.submitcheck = function() {
        return this.each(function(){
    
            var t = $(this); // get jQuery version of 'this'
            
            $(this).mouseup( function() {
                $(this).attr("disabled","disabled")
                $(this).val("We're working on it...")
            })
        
        })
    
    }
    
  7. Chris On 21st March 2008 at 15:03

    May have just answered my own question - if I put this line in it submits the form and does the other stuff.

    $(”form”).submit();

  8. Benedikt D Valdez On 20th April 2008 at 17:04

    I am having trouble with getting this to work on my own server..

    I got the source code from here, and opened it, but it doesn’t work, only thing I get is “This username is free”

    Any ideas?

  9. raj madhukar On 5th May 2008 at 08:05

    it is very esay to learn coading php and other

  10. Chrissie On 13th May 2008 at 20:05

    Hi, I have copied the example and all i get is the throbber and ‘checking username’ and it doesnt get any further than that. any help to get it working would be appreciated. thanks!

  11. Chrissie On 13th May 2008 at 20:05

    ok, i fixed my own problem, turned out the server was running php4, switching it to php5 made it work a treat. many thanks (would like to know btw if creating a username array from the db is the best solution, OR checking a “select * where username = ‘username’ etc is best. Thanks)

  12. destroy On 14th May 2008 at 11:05

    Good, but if you write a symbol “&” and then every symbol is a OK.

  13. Richard On 13th June 2008 at 14:06

    Fantastic tutorial. Exactly the simpicity I was looking for, and works a charm!

  14. Richard On 14th June 2008 at 01:06

    So I’m trying to use this tutorial as a basis for checking two password fields:

    1) Are valid passwords 2) both fields match each other

    It’s not too difficult, except for one problem. If a user types their password into field one incorrectly, then types it into field two correctly, the second field is right, but it will fail validation. So the user will go back to the first field and correct their password, but the second password field will still show as invalid.

    I haven’t quite figured out how to fire off the password 2 validation function when the first field is modified….

    Actually, I think I might have figured it out in my head while I was just explaining it here.

    Anyway, it would be nice to see a tutorial here on AJAX password validation when there is a password field and a password confirmation field.

  15. Remy On 14th June 2008 at 13:06

    @Richard - I assume by “AJAX” you actually mean interactive - rather than some kind of client-server communication. Certainly you don’t need client-server comms just to validate against a password. A good starting point would be the jquery validation plugin. Good luck.

  16. Faith Rivenbank On 18th June 2008 at 03:06

    Great! I love it :)

  17. nOON On 3rd July 2008 at 00:07

    Cool! How can I show the ajax loader image when the form has been submitted?

  18. Clinicas Dentarias On 17th July 2008 at 02:07

    Hi

    You code is fenomenal. Works fine in a example like the one you mentioned.

    I´ve tried to implement this on my site, but i’m using a bigger form (with more then 3 variables to check) , can’t make it work…

    Cheers

  19. Jase On 29th August 2008 at 21:08

    With the username validation what happens if you have international characters for example using a-z wont work? What is the work around for this?

  20. pram On 5th November 2008 at 12:11

    im trying to do sample ajax validation of user name using jsp n servlet by refering sun java article “Realtime Form Validation Using Ajax” but its not working…..

  21. Kevin Womack On 5th November 2008 at 19:11

    Yes, I downloaded the ajax-validation code and when I run on my unix server, running PHP5.2, the …. checking availability stays all the time. It never hits the check_username function.

  22. Kevin Womack On 5th November 2008 at 22:11

    Never mind….. I’m an idiot!

  23. Sundeep On 4th December 2008 at 19:12

    Is there any possibility of validating two field in ajax in the same form

  24. Elementis On 30th December 2008 at 22:12

    Im having the same problem Womack had. The script is just showing …checking availability. Anybody have any solutions to this problem. Im sure it could help me and other people that try to use this code as well.

  25. Elementis On 30th December 2008 at 22:12

    Crap haha now I feel like an idiot I figured it out too. Hours of coding can make eyes wary of the littlest things. Dont forget to rename to your page files in the script! haha

Leave your own comment
  • http://