Drupal Ajax Form Validation

Ajax form validation is one of those features typically tasked to a Drupal Developer. Here is how it is accomplished in Drupal 6.

Let's say we were adding Ajax form validation to the user registration page. You need to create a jQuery event listener in a javascript file.

$(document).ready(function(){    
  $("#edit-name").blur(function () {
    $.post('modulename/validate', { name: this.value }, function(data) {
      $('#edit-name-wrapper .description').append(data);
    });
  });
 });

What this does is when the user clicks away from the username field it takes the value of that field and does an HTTP POST to modulename/validator (we will actually set up this url in a minute). If the name isn't valid, or we need to display some sort of error message, we append this to the description, or you could just define a new div to place stuff into.

Now, let's set up our custom module. You need to create a modulename directory in sites/all/modules then inside that directory create 2 files modulename.module and modulename.info with a little bit of information about your module. See http://drupal.org/node/206756 for reference. Now open up your .module file and let's create the url.

 

/**
* Implementation of hook_menu().
*/
function modulename_menu () {
  $items['modulename/validate'] = array(
    'page callback' => "modulename_ajax_validate",
    'page arguments' => array(2),
    'type' => MENU_CALLBACK,
  );
  
  return $items;
}

function modulename_ajax_validate ($string = '') {
  if ($string) {
    //do your validation here...say we didn't want to allow underscores in the username
    if(strstr($string,"_")) {
      $errors[] = t("Underscores in your username aren't allowed.");
    }
    foreach ($errors as $error) {
      print "$error <br />";
    }
  }
}

What this does is creates a path for the validation (modulename/validate) and then calls a function (there's nothing special about this function name, you could have called it foo_validateme) passing it the string parameter parameter. Then if the validation fails, it adds a string to the errors array. If there are errors, loop through the errors and print them out. This string gets passed back to our jQuery handler we wrote above as the variable name: data and gets printed out and appended to the description of the username field.

You could try this example, but it also might be prudent to have a look at the Ajax Project on Drupal.org.

Dear fellow Drupal Developer, you are now armed with the awesomeness of Ajax. Happy validating!

UPDATE: Several readers have recommended using the jQuery Validation plugin. This is a great plugin and have used it many times. I suggest you check it out. Also, there is a good example of doing AHAH in the examples module on drupal.org. Another reader commented that it would be a great idea to use the same validation function name so that the form would be validated by the same code using Ajax or just normal form submission. For this to work, you would need to get the name right using the Drupal Form API. Here is an example of how to do that.

(Since you asked me to link

(Since you asked me to link to this on my blog) - This is nice, but I would suggest that you're not doing anything here that can't be done more easily with the jQuery Validate plugin. What would be really valuable is if you validated *the actual form* via ajax -- i.e. pass the values from the user through the original $form's validation (as if it were submitted and validated server-side) -- then only one validate hook is needed and it works identicallt even if javascript is turned off. Ben B

Thanks for your feedback Ben.

Thanks for your feedback Ben. I have used the jQuery Validate plugin http://docs.jquery.com/Plugins/Validation before, but wanted to keep this as simple as possible...This was originally written in response to a fellow Drupaler's question on drupal.org and I didn't know if he had any familiarity with the jQuery Validate plugin or not...But that is a good solution as well. I also think it's a great idea to use the same validation function that the form uses that way only one validation function is needed for less code to maintain.

Interesting and simple

Interesting and simple approach. Question: How does using $.post cause the value entered to appear as arg(2)? Shouldn't the validate function use $_POST instead? Doing it via the URL would work if you used jQuery.get... But then you have the issue of the value being validated containing a slash (which would cause the value to be separated up as multiple arguments).

Great post, very useful. One

Great post, very useful. One question: shouldn't the key in $items['modulename/validate'] match the first parameter in $.post('modulename/validator', { name: this.value }, function(data)?

Great Catch. I've updated the

Great Catch. I've updated the post.

Bookmarked! We are certainly

Bookmarked! We are certainly going to add this to our repertoire!