Magento form field AJAX validation

In this short article I will show you a quick way of adding an AJAX-ed validation on Magento form field. If you open up the {MAGENTO_ROOT}/js/prototype/validation.js file and look into its header comments you will see that Magento’s JavaScript validation is actually done trough 3rd party JavaScript library called Really Easy Field Validation by an author named Andrew Tetlaw, with its own GIT repository available here.

As the name suggests, validation is really easy to implement and use. It is based on the basic method of attaching to the form’s onsubmit event, read out all the form elements’ classes and perform validation if required. If a field fails validation, reveal field validation advice and prevent the form from submitting. So basically in Magento you end up with form fields like

<input class="required validate-number" id="field1" name="field1" />

Here is the list of validation classes defined by default Really Easy Field Validation:

  • required (not blank)
  • validate-number (a valid number)
  • validate-digits (digits only)
  • validate-alpha (letters only)
  • validate-alphanum (only letters and numbers)
  • validate-date (a valid date value)
  • validate-email (a valid email address)
  • validate-url (a valid URL)
  • validate-date-au (a date formatted as; dd/mm/yyyy)
  • validate-currency-dollar (a valid dollar value)
  • validate-selection (first option e.g. ‘Select one…’ is not selected option)
  • validate-one-required (At least one textbox/radio element must be selected in a group)

However, if you take a detailed look at the code within {MAGENTO_ROOT}/js/prototype/validation.js file you will notice several new validation rules:

  • validate-no-html-tags
  • validate-select
  • required-entry
  • validate-number
  • validate-number-range
  • validate-digits-range
  • validate-url
  • validate-ssn
  • validate-zip-international
  • and few others…

Even with all those validations, custom requirements can sometimes ask for more. For example, imagine you are not satisfied with the validate-email validation. You are not satisfied with it because it only does the regular expression validation and not the “real deal”. Imagine you want to check if each email address actually exist in the world, not just if it is in proper format. For example, email address inchoo999888777@gmail.com would pass the built in regular expression based validation but thats not the existing email address. Webservices like http://www.towerdata.com/ can give you an option of validating email for its existence. Their API is simple, just pass the email address and check the response. Now, how do we make AJAX-ed validation rule?

Here is a code snippet that does exactly that (skin folder… /js/email/towerdata-validation.js):

Validation.add('validate-email', 'Please enter a valid email address. For example johndoe@domain.com.', function(v) {
 
var url = '/mycontroller/myValidateAction/email?email=' + encodeURIComponent(v);
 
var ok = false;
 
new Ajax.Request(url, {
method: 'get',
asynchronous: false,
onSuccess: function(transport) {
var obj = response = eval('(' + transport.responseText + ')');
validateTrueEmailMsg = obj.status_desc;
 
if (obj.ok === false) {
Validation.get('validate-email').error = validateTrueEmailMsg;
ok = false;
} else {
ok = true; /* return true or false */
}
},
onComplete: function() {
 
if ($('advice-validate-email-email')) {
$('advice-validate-email-email').remove();
}
 
if ($('advice-validate-email-email_address')) {
$('advice-validate-email-email_address').remove();
}
 
if ($('advice-validate-email-billing:email')) {
$('advice-validate-email-billing:email').remove();
}
 
if ($('advice-validate-email-shipping:email')) {
$('advice-validate-email-shipping:email').remove();
}
 
if ($('advice-validate-email-_accountemail')) {
$('advice-validate-email-_accountemail').remove();
}
}
});
 
return ok;
});

Example above does an synchronous AJAX call towards the custom controller action which in turn calls and handles the response from http://www.towerdata.com/ API then returns the proper response to the AJAX. The example above is not the perfect JavaScript code as I am not that into the JavaScript but it does the job. The only problem is the possible lag time of 2-4 seconds on the frontend until the AJAX executes (that is until the towerdata API gives response). Please keep in mind that although I am referencing http://www.towerdata.com API, this AJAX-ed approach can be used on anything, not just email validation.

Additionally you will notice I used “Validation.add(‘validate-email’…” to define a new rule. Since that rule already exists in the {MAGENTO_ROOT}/js/prototype/validation.js file, defining it later would simply rewrite it. Meaning you would not have to change any of the *.phtml files calling the validate-email class on input fields. If you wish to create a completely new rule, you simple give it a new name, one that hasn’t been already used.

And finally, once you have defined your rule you need to “include” it in head of the html file by doing something like this in layout xml file of your Magento theme:

<default>
<reference name="head">
<action method="addItem"><type>skin_js</type><name>js/email/towerdata-validation.js</name></action>
</reference>
</default>

Hope this helps. Cheers.