AJAX Form Validation: Part 1

Exclusive offer: get 50% off this eBook here
AJAX and PHP: Building Modern Web Applications 2nd Edition

AJAX and PHP: Building Modern Web Applications 2nd Edition — Save 50%

Build user friendly Web 2.0 Applications with JavaScript and PHP

€18.99    €9.50
by Audra Hendrix Bogdan Brinzarea Cristian Darie | February 2010 | AJAX MySQL PHP Web Development

In this two-part article by Audra Hendrix, Bogdan Brinzarea and Cristian Darie, authors of AJAX and PHP: Building Modern Web Applications 2nd Edition, we will create a form validation application that implements traditional techniques with added AJAX flavor, thereby making the form more user-friendly, responsive, and pleasing. In the AJAX world, entered data is validated on the fly, so the users are never confronted with waiting for full-page reloads or the rude "blank form" as a reply.

The server is the last line of defense against invalid data, so even if you implement client-side validation, server-side validation is mandatory. The JavaScript code that runs on the client can be disabled permanently from the browser's settings and/or it can be easily modified or bypassed.

Implementing AJAX form validation

The form validation application we will build in this article validates the form at the server side on the classic form submit, implementing AJAX validation while the user navigates through the form. The final validation is performed at the server, as shown in Figure 5-1:

AJAX and PHP- AJAX Form Validation

Doing a final server-side validation when the form is submitted should never be considered optional. If someone disables JavaScript in the browser settings, AJAX validation on the client side clearly won't work, exposing sensitive data, and thereby allowing an evil-intentioned visitor to harm important data on the server (for example, through SQL injection).

Always validate user input on the server.

As shown in the preceding figure, the application you are about to build validates a registration form using both AJAX validation (client side) and typical server-side validation:

  • AJAX-style (client side): It happens when each form field loses focus (onblur). The field's value is immediately sent to and evaluated by the server, which then returns a result (0 for failure, 1 for success). If validation fails, an error message will appear and notify the user about the failed validation, as shown in Figure 5-3.
  • PHP-style (server side): This is the usual validation you would do on the server—checking user input against certain rules after the entire form is submitted. If no errors are found and the input data is valid, the browser is redirected to a success page, as shown in Figure 5-4. If validation fails, however, the user is sent back to the form page with the invalid fields highlighted, as shown in Figure 5-3.

Both AJAX validation and PHP validation check the entered data against our application's rules:

  • Username must not already exist in the database
  • Name field cannot be empty
  • A gender must be selected
  • Month of birth must be selected
  • Birthday must be a valid date (between 1-31)
  • Year of birth must be a valid year (between 1900-2000)
  • The date must exist in the number of days for each month (that is, there's no February 31)
  • E-mail address must be written in a valid email format
  • Phone number must be written in standard US form: xxx-xxx-xxxx
  • The I've read the Terms of Use checkbox must be selected

Watch the application in action in the following screenshots:

AJAX and PHP- AJAX Form Validation

AJAX and PHP- AJAX Form Validation

AJAX and PHP- AJAX Form Validation

XMLHttpRequest, version 2

We do our best to combine theory and practice, before moving on to implementing the AJAX form validation script, we'll have another quick look at our favorite AJAX object—XMLHttpRequest.

On this occasion, we will step up the complexity (and functionality) a bit and use everything we have learned until now. We will continue to build on what has come before as we move on; so again, it's important that you take the time to be sure you've understood what we are doing here. Time spent on digging into the materials really pays off when you begin to build your own application in the real world.

Our OOP JavaScript skills will be put to work improving the existing script that used to make AJAX requests. In addition to the design that we've already discussed, we're creating the following features as well:

  • Flexible design so that the object can be easily extended for future needs and purposes
  • The ability to set all the required properties via a JSON object

We'll package this improved XMLHttpRequest functionality in a class named XmlHttp that we'll be able to use in other exercises as well. You can see the class diagram in the following screenshot, along with the diagrams of two helper classes:

  • settings is the class we use to create the call settings; we supply an instance of this class as a parameter to the constructor of XmlHttp
  • complete is a callback delegate, pointing to the function we want executed when the call completes

The final purpose of this exercise is to create a class named XmlHttp that we can easily use in other projects to perform AJAX calls.

AJAX and PHP- AJAX Form Validation

With our goals in mind, let's get to it!

Time for action – the XmlHttp object

  1. In the ajax folder, create a folder named validate, which will host the exercises in this article.
AJAX and PHP: Building Modern Web Applications 2nd Edition Build user friendly Web 2.0 Applications with JavaScript and PHP
Published: December 2009
eBook Price: €18.99
Book Price: €30.99
See more
Select your format and quantity:
  1. In the validate folder, create a new file named xhr.js and add the following code to it:
    // XmlHttp constructor can receive request settings:
    // url - the server url
    // contentType - request content type
    // type - request type (default is GET)
    // data - optional request parameters
    // async - whether the request is asynchronous (default is true)
    // showErrors - display errors
    // complete - the callback function to call when the request
    // completes
    function XmlHttp(settings)
    {
    // store the settings object in a class property
    this.settings = settings;
    // override default settings with those received as parameter
    // the default url points to the current page
    var url = location.href;
    if (settings.url)
    url = settings.url;
    // the default content type is the content type for forms
    var contentType = "application/x-www-form-urlencoded";
    if (settings.contentType)
    contentType = settings.contentType;
    // by default the request is done through GET
    var type = "GET";
    if(settings.type)
    type = settings.type;
    // by default there are no parameters sent
    var data = null;
    if(settings.data)
    {
    data = settings.data;
    // if we go through GET we properly adjust the URL
    if(type == "GET")
    url = url + "?" + data;
    }
    // by default the postback is asynchronous
    var async = true;
    if(settings.async)
    async = settings.async;
    // by default we show all the infrastructure errors
    var showErrors = true;
    if(settings.showErrors)
    showErrors = settings.showErrors;
    // create the XmlHttpRequest object
    var xhr = XmlHttp.create();
    // set the postback properties
    xhr.open(type, url, async);
    xhr.onreadystatechange = onreadystatechange;
    xhr.setRequestHeader("Content-Type", contentType);
    xhr.send(data);
    // the function that displays errors
    function displayError(message)
    {
    // ignore errors if showErrors is false
    if (showErrors)
    {
    // display error message
    alert("Error encountered: n" + message);
    }
    }
    // the function that reads the server response
    function readResponse()
    {
    try
    {
    // retrieve the response content type
    var contentType = xhr.getResponseHeader("Content-Type");
    // build the json object if the response has one
    if (contentType == "application/json")
    {
    response = JSON.parse(xhr.responseText);
    }
    // get the DOM element if the response is XML
    else if (contentType == "text/xml")
    {
    response = xhr.responseXml;
    }
    // by default get the response as text
    else
    {
    response = xhr.responseText;
    }
    // call the callback function if any
    if (settings.complete)
    settings.complete (xhr, response, xhr.status);
    }
    catch (e)
    {
    displayError(e.toString());
    }
    }
    // called when the request state changes
    function onreadystatechange()
    {
    // when readyState is 4, we read the server response
    if (xhr.readyState == 4)
    {
    // continue only if HTTP status is "OK"
    if (xhr.status == 200)
    {
    try
    {
    // read the response from the server
    readResponse();
    }
    catch(e)
    {
    // display error message
    displayError(e.toString());
    }
    }
    else
    {
    // display error message
    displayError(xhr.statusText);
    }
    }
    }
    }
    // static method that returns a new XMLHttpRequest object
    XmlHttp.create = function()
    {
    // will store the reference to the XMLHttpRequest object
    var xmlHttp;
    // create the XMLHttpRequest object
    try
    {
    // assume IE7 or newer or other modern browsers
    xmlHttp = new XMLHttpRequest();
    }
    catch(e)
    {
    // assume IE6 or older
    try
    {
    xmlHttp = new ActiveXObject("Microsoft.XMLHttp");
    }
    catch(e) { }
    }
    // return the created object or display an error message
    if (!xmlHttp)
    alert("Error creating the XMLHttpRequest object.");
    else
    return xmlHttp;
    }

  2. To quickly test the functionality of your XmlHttp class, create a new file named xhrtest.html and add the following code to it:
    <html>
    <head>
    <script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="xhr.js"></script>
    </head>
    <body>
    <div id="test">
    </div>
    <script>
    XmlHttp
    ({url:'async.txt',
    complete:function(xhr,response,status)
    {
    document.getElementById("test").innerHTML = response;
    }
    });
    </script>
    </body>
    </html>
  3. Now create async.txt with some text in it, and then load http://localhost/ajax/validate/xhrtest.html. Figure below shows our result:

    AJAX and PHP- AJAX Form Validation

What just happened?

The code listed above contains significant code from the previous examples and then some new code. Let's break it down into small pieces and analyze it.

The chosen name for our reusable object is XmlHttp. Its functionality is wrapped in two functions:

  • XmlHttp.create(): A static method of the XmlHttp object that creates a XmlHttpRequest object
  • XmlHttp(): The constructor of the XmlHttp object

From a design point of view, the XmlHttp object represents a wrapper around the XmlHttpRequest object. The XmlHttp.create() method contains the same code that we have previously seen in the createXmlHttpRequestObject() method. It simply acts like a factory for an XmlHttpRequest object.

The constructor of the XmlHttp object, although it can look quite scary at first sight, actually contains very simple code. The constructor receives as a parameter a JSON object containing all the settings for the XmlHttp object. Choosing a JSON object is both convenient from the extensibility point of view and easy from the programming point of view. We store the settings in a property with the same name.

function XmlHttp(settings)
{
// store the settings object in a class property
this.settings = settings;

The settings object contains the following properties that will be mainly used for the XmlHttpRequest object:

  • url: The URL of the AJAX request
  • type: The type of the request (GET or POST)
  • contentType: The content type of the request
  • data: The data to be sent to the server
  • async: A flag that specifies whether the request is synchronous or asynchronous
  • complete: The function called when the request completes
  • showErrors: A flag that indicates whether infrastructure errors will be displayed or not

These are the parameters required to make an AJAX request. Even though the structure and the design of this object are simple, it can be easily extended with more advanced features, giving us the flexibility feature we defined as a goal.

The flexibility offered by JSON objects means we don't force the user to pass all the properties mentioned above each time the object is created. Instead, we created a standard set of default values that the user can choose to overwrite when necessary. The next few lines simply implement this logic.

Making a request through GET or POST is different and we take care of it when setting the parameters for the request:

// by default there are no parameters sent
var data = null;
if(settings.data)
{
data = settings.data;
// if we go through GET we properly adjust the URL
if(type == "GET")
url = url + "?" + data;
}

After having all the settings for the AJAX request, we create the XmlHttpRequest and we open it.

// create the XmlHttpRequest object
var xhr = XmlHttp.create();
// set the postback properties
xhr.open(type, url, async);

The next step is to hook to the readystatechange event:

xhr.onreadystatechange = onreadystatechange;

The handler function is a inner function of the constructor and contains the same code as the handleRequestStateChange() method that you already know.

Probably the most interesting piece of code is in the response handler. The readResponse() inner function is responsible for handling the response received from the server. It gets the content type of the response and, based on that, it builds the response JSON object or it retrieves the response as an XML element. If no matching content type is found, the raw text of the response is used instead.

// retrieve the response content type
var contentType = xhr.getResponseHeader("Content-Type");
// build the json object if the response has one
if (contentType == "application/json")
{
response = JSON.parse(xhr.responseText);
}
// get the DOM element if the response is XML
else if (contentType == "text/xml")
{
response = xhr.responseXml;
}
// by default get the response as text
else
{
response = xhr.responseText;
}

After gathering the necessary data, the XmlHttp object passes it all to the callback function (settings.complete()) along with the XmlHttp object and the HTTP response code.

// call the callback function if any
if (settings.complete)
settings.complete (xhr, response, xhr.status);

All in all, the next time you need to call a server script asynchronously from a web page, you can count on XmlHttp to do all the dirty work. You just tell it what URL to contact, specifying the necessary parameters, and it fetches the response for you.

>> Continue Reading AJAX Form Validation: Part 2

 

[ 1 | 2 ]

If you have read this article you may be interested to view :

AJAX and PHP: Building Modern Web Applications 2nd Edition Build user friendly Web 2.0 Applications with JavaScript and PHP
Published: December 2009
eBook Price: €18.99
Book Price: €30.99
See more
Select your format and quantity:

About the Author :


Audra Hendrix

Audra Hendrix was educated at Northwestern University. She works as a consultant in applied technology and marketing to small and medium-sized businesses. While her client list includes Fortune 500 companies, she prefers the flexibility, agility, and challenges of small to medium-sized businesses. She has consulted both in the United States and France for businesses seeking to better utilize their resources and maximize their gains by reinventing and reapplying back office and Internet applications, data management, cost-effective marketing strategies, staffing requirements, and planning and deployment of new or emerging product lines.

Bogdan Brinzarea

Bogdan has a strong background in Computer Science holding a Master and Bachelor Degree at the Automatic Control and Computers Faculty of the Politehnica University of Bucharest, Romania and also an Auditor diploma at the Computer Science department at Ecole Polytechnique, Paris, France.

His main interests cover a wide area from embedded programming, distributed and mobile computing and new web technologies. Currently, he is employed as an Alternative Channels Specialist at Banca Romaneasca, Member of National Bank of Greece where he is responsible for the Internet Banking project and coordinates other projects related to security applications and new technologies to be implemented in the banking area.

Cristian Darie

Cristian Darie is a software engineer with experience in a wide range of modern technologies, and the author of numerous books, including his popular AJAX and PHP tutorial by Packt, his ASP.NET E-Commerce tutorial, by APress and his forthcoming SEO tutorial for PHP developers by Wrox Press. Cristian is studying distributed application architectures for his PhD, and is getting involved with various commercial and research projects. When not planning to buy Google, he enjoys his bit of social life. If you want to say "hi", you can reach Cristian through his personal website at http://www.cristiandarie.ro.

Books From Packt

Drupal 6 Performance Tips
Drupal 6 Performance Tips

Mahara 1.2 E-Portfolios: Beginner's Guide
Mahara 1.2 E-Portfolios: Beginner's Guide

Joomla! 1.5 Multimedia
Joomla! 1.5 Multimedia

jQuery 1.4 Reference Guide
jQuery 1.4 Reference Guide

Backbase 4 RIA Development
Backbase 4 RIA Development

Grok 1.0 Web Development
Grok 1.0 Web Development

Joomla! 1.5: Beginner's Guide
Joomla! 1.5: Beginner's Guide

CMS Made Simple 1.6: Beginner's Guide
CMS Made Simple 1.6: Beginner's Guide

Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software