AJAX Form Validation: Part 1

Build user friendly Web 2.0 Applications with JavaScript and PHP

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.
  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="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 :

Books to Consider

comments powered by Disqus
X

An Introduction to 3D Printing

Explore the future of manufacturing and design  - read our guide to 3d printing for free