jQuery form validation using JSON object and PHP

By LeonRevill
Mon, 2012-11-26 09:37
13 comments

Share with Others

Tutorial by Leon Revill from Revill Web Design. I work with PHP, jQuery, HTML, CSS and mySQL every day and pass my knolwedge on through my web development blog

jQuery form validation using JSON object and PHP

There are no shortage of examples or tutorials showing you how to validate a form using jQuery and PHP but not many utilize the JSON object the most efficient way. This tutorial will also use Twitter Bootstrap to provide the UI elements and HTML layout for the tutorial.

Bootstrap HTML form

Bootstrap allows us to quickly create a HTML form so we can get to the juicy bits of this tutorial.

<!DOCTYPE html>
<head>
    <script type='text/javascript' src='<a href="http://code.jquery.com/jquery.min.js'></script>
">http://code.jquery.com/jquery.min.js'></script>
</a>    <script src="../bootstrap/js/bootstrap.min.js"></script>
    <script src='script.js'></script>
    <link href="../bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
    <link media="screen" href='style.css' rel="stylesheet" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <div id='frame'>
        <h1>Register Form</h1>
        <div id='response' class='alert alert-success'></div>
        <form class='form-horizontal' id="form1">
            <div class='control-group'>
                <label class="control-label">Username:</label>
                <div class='controls'>
                    <input type='text' class='input-large' placeholder='Username' id='username' />
                </div>
            </div>
            <div class='control-group'>
                <label class="control-label">Real Name:</label>
                <div class='controls'>
                    <input type='text' class='input-large' placeholder='Real Name' id='real-name' />
                </div>
            </div>
            <div class='control-group'>
                <label class="control-label">E-Mail:</label>
                <div class='controls'>
                    <input type='text' class='input-large' placeholder='E-Mail' id='email' />
                </div>
            </div>
            <a href='#' class='btn btn-inverse btn-large pull-right submit-btn'><i class='icon-ok icon-white'></i> Submit</a>
        </form>
    </div>
</body>

So, this creates us a simple but good looking form so now we can move onto the jQuery. The jQuery needs to collect all the data from the form when the submit button is pressed, send it to the PHP for validation, grab the returned data and check it for any errors.

If there are any errors then the jQuery needs to interpret the JSON objects provided by the PHP, highlight the associated field and provide the correct error message. Let's begin.

$(function(){
    $('.submit-btn').click(function(){
        var formInputs = new Array();
        //Get the form ID
        var id = $(this).parent().attr('id');
        $('#' + id + ' input').each(function(){
            //Get the input value
            var inputValue = $(this).val();
            //Get the input id
            var inputId = $(this).attr('id');
            //Add them to the array
            formInputs[inputId] = inputValue; 
        });
    });
});

What this bit of code is doing is catching the button click of the submit-btn in a form, then checking the buttons parent for an id, using that id to then find all the input's within it and then storing the inputs id and value in an array which we can then send to the PHP script we are going to write later.

To actually send the array to the PHP we need to use an ajax call which will do a POST request to the PHP script, this is how it will look:

$(function(){
    $('.submit-btn').click(function(){
        var formInputs = new Array();
        //Get the form ID
        var id = $(this).parent().attr('id');
        $('#' + id + ' input').each(function(){
            //Get the input value
            var inputValue = $(this).val();
            //Get the input id
            var inputId = $(this).attr('id');
            //Add them to the array
            formInputs[inputId] = inputValue; 
        });
        $.ajax({
            url: 'url/to/script/here.php',
            type: 'POST',
            data: {
                inputs: formInputs
            },
            success: function(data) {
 
            }
        });
    });
});

This code will post a variable called "inputs" to the PHP script containing all the data we previously populated it with, lets jump into the PHP script now:

<?php
    //Create an array to store data that we will send back to the jQuery
    $data = array(
        'success' => false, //Flag whether everything was successful
        'errors' => array() //Provide information regarding the error(s)
    );
 
    //Check to make sure that the inputs variable has been posted
    if (isset($_POST['inputs'])) {
        //Store the posted data into an array
        $inputs = $_POST['inputs'];
        //Loop through each input field
        foreach ($inputs as $input) {
            $id = $input['id'];
            $value = $input['value'];
            //Determine what validation we need to be doing
            switch($id) {
                //Username and real name need the same validation, so only need one case block here
                case "username":
                case "real-name":
                    //Ensure that they are both at least 6 characters long
                    if (strlen($value) < 6) {
                        //To make it more readable, replace the "-"'s with spaces and make the first character upper case
                        $msg = "Your " . str_replace("-", " ", ucfirst($id)) . " must be at least 6 characters in length";
                    }
                    break;
                case "email":
                    //Use PHP filter to validate the E-Mail address
                    if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
                        $msg = "You must provide a valid e-mail address";
                    }
                    break;
                default:
                        //If some field has been passed over, we report the error
                        $msg = "Sorry, we don't understand this data, please try again";
                    break;
            }
            //If there is an error, add it to the errors array with the field id
            if (!empty($msg)) {
                $data['errors'][] = array(
                    'msg' => $msg,
                    'field' => $id
                );
            }
        }
 
        //Validation over, was it successful?
        if (empty($data['errors'])) {
            $data['success'] = true;
        }
 
    } else {
        $data['errors'][] = "Data missing";
    }
 
    //Set the content type and charset to ensure the browser is expecting the correct data format, also ensure charset is set-to UTF-8 and not utf8 to prevent any IE issues
    header("Content-Type: application/json; charset=UTF-8");
    echo json_encode((object)$data);
?>

The code is very well commented so most aspects should be easily understood, lets go over the main parts now.

if (isset($_POST['inputs'])) {
        //Store the posted data into an array
        $inputs = $_POST['inputs'];
        //Loop through each input field
        foreach ($inputs as $input) {
            $id = $input['id'];
            $value = $input['value'];

Here we check that the inputs were posted correctly and store them in a variable, which will be an array. We then loop through each of the inputs and create two more variables which we will then us to determine how the data needs to be validated.

//Determine what validation we need to be doing
switch($id) {
    //Username and real name need the same validation, so only need one case block here
    case "username":
    case "real-name":
        //Ensure that they are both at least 6 characters long
        if (strlen($value) < 6) {
        //To make it more readable, replace the "-"'s with spaces and make the first character upper case
        $msg = "Your " . str_replace("-", " ", ucfirst($id)) . " must be at least 6 characters in length";
        }
        break;
    case "email":
        //Use PHP filter to validate the E-Mail address
        if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
        $msg = "You must provide a valid e-mail address";
        }
        break;
    default:
        //If some field has been passed over, we report the error
        $msg = "Sorry, we don't understand this data, please try again";
        break;
}

This switch statement looks at the $id variable and decides what type of validation is required, if the $value variable does not pass the validation, we then create a $msg variable which holds the error message for that field.

//Validation over, was it successful?
if (empty($data['errors'])) {
    $data['success'] = true;
}

If there is an error message, then we add this and the field id to the main $data array which will be passed back to the jQuery.

    //Set the content type and charset to ensure the browser is expecting the correct data format, also ensure charset is set-to UTF-8 and not utf8 to prevent any IE issues
    header("Content-Type: application/json; charset=UTF-8");
    echo json_encode((object)$data);

Once validation is complete, we set the headers as explained in the code comments and then json_encode and cast the array to an object so we can reference the data within jQuery as data.success as opposed to data['success'].

This will then send a response back to the jQuery which will look something like this:

{
    "success":false,
    "errors":[
        {
            "msg":"Your Username must be at least 6 characters in length",
            "field":"username"
        },
        {
            "msg":"Your Real name must be at least 6 characters in length",
            "field":"real-name"},
        {
            "msg":"You must provide a valid e-mail address",
            "field":"email"
        }
    ]
}

Now we have a PHP script that takes the data provided, validates it and provides an appropriate response, lets complete the jQuery script.

$(function(){
    //Hide the error/success message response on load
    $('#response').hide();
    $('.submit-btn').click(function(){
        //Hide the reponse from last time
        $('#response').hide();
        var formInputs = new Array();
        //Get the form ID
        var id = $(this).parent().attr('id');
        $('#' + id + ' input').each(function(){
            //Remove any previously set errors
            $(this).removeClass('error');
            //Create a temp object that holds the input data
            var obj = {
                'value': $(this).val(),
                'id': $(this).attr('id')
            };
            //Add the object to the array
            formInputs.push(obj); 
        });
        $.ajax({
            url: 'validate.php',
            type: 'POST',
            data: {
                'inputs': formInputs
            },
            success: function(data) {
                //Check to see if the validation was successful
                if (data.success) {
                    //Turn the response alert into a success alert
                    $('#response').addClass('alert-success');
                    $('#response').removeClass('alert-error');
                    //Add the success message text into the alert
                    $('#response').html("<i class='icon-ok'></i> Form validated successfully!").fadeIn();
                } else {
                    //There were some errors
                    //Turn the response alert into an error alert
                    $('#response').removeClass('alert-success');
                    $('#response').addClass('alert-error');
                    //Create a message and a HTML list to display in the response alert
                    var list = "<p><i class='icon-remove-sign'></i> There following errors occured: </p><ul>";
                    $.each(data.errors, function(){
                        $('#' + this.field).addClass('error');
                        list += "<li>" + this.msg + "</li>";
                    });
                    list += "</ul>";
                    //Add the HTML to the response alert and fade it in
                    $('#response').html(list).fadeIn();
                }
            }
        });
    });
});

Once more the code is well commented to make it as easy to understand as possible. Lets take a look at how this jQuery handles the response from the PHP.

success: function(data) {
    //Check to see if the validation was successful
    if (data.success) {
 
        //Turn the response alert into a success alert
        $('#response').addClass('alert-success');
        $('#response').removeClass('alert-error');
 
        //Add the success message text into the alert
        $('#response').html("<i class='icon-ok'></i> Form validated successfully!").fadeIn();
 
    } else {
 
        //There were some errors
        //Turn the response alert into an error alert
        $('#response').removeClass('alert-success');
        $('#response').addClass('alert-error');
 
        //Create a message and a HTML list to display in the response alert
        var list = "<p><i class='icon-remove-sign'></i> There following errors occurred: </p><ul>";
 
        $.each(data.errors, function(){
            $('#' + this.field).addClass('error');
            list += "<li>" + this.msg + "</li>";
        });
 
        list += "</ul>";
 
        //Add the HTML to the response alert and fade it in
        $('#response').html(list).fadeIn();
    }
}

The "data" variable within the success function() will hold the JSON objects that is sent back from the PHP, the first thing we do is check to see if there was a successful validation or not by doing:

    if (data.success) {

The PHP will set this to true if there were no error messages created from the validation. If this is set to true then we just add and remove a class from the alert to display a nicely styled success message, thanks to twitter bootstrap.

If success is set to false, then we need to loop through each of the messages and add the .error class to the input elements which will turn them red and then display a list of errors within the alert, using the following code:

    //There were some errors
    //Turn the response alert into an error alert
    $('#response').removeClass('alert-success');
    $('#response').addClass('alert-error');
 
    //Create a message and a HTML list to display in the response alert
    var list = "<p><i class='icon-remove-sign'></i> There following errors occured: </p><ul>";
 
    //Loop through each error message and add it to the list
    $.each(data.errors, function(){
        $('#' + this.field).addClass('error');
        list += "<li>" + this.msg + "</li>";
    });
 
    list += "</ul>";
 
    //Add the HTML to the response alert and fade it in
    $('#response').html(list).fadeIn();

And that's it! All there is to do is add some CSS so it looks very nice! Here you go:

/* Lets use a Google Web Font :) */
@import url(<a href="http://fonts.googleapis.com/css?family=Finger+Paint">http://fonts.googleapis.com/css?family=Finger+Paint</a>);
/* Basic CSS for positioning etc */
body {
    font-family: 'Finger Paint', cursive;
    background-image: url('bg.jpg');
}
#frame {
    width: 400px;
    margin: auto;
    margin-top: 125px;
    border: solid 1px #CCC;
    /* SOME CSS3 DIV SHADOW */
    -webkit-box-shadow: 0px 0px 10px #CCC;
    -moz-box-shadow: 0px 0px 10px #CCC;
    box-shadow: 0px 0px 10px #CCC;
    /* CSS3 ROUNDED CORNERS */
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
    -khtml-border-radius: 5px;
    border-radius: 5px;
    background-color: #FFF;
}
#form1 {
    padding: 20px;
    min-height: 150px;
}
#form1 input {
    width: 100%;
}
#form1 label {
    width: 80px;
}
#form1 .controls {
    margin-left: 110px;
}
#frame h1 {
    padding: 20px;
    padding-bottom: 0px;
}
#frame .alert {
    margin: 10px;
}
#form1 .error {
    border: solid 2px red;
    color: red;
}

You can view a demo here or download all the files here. Thank you and I hope this has helped!

Comments

Thanks for the tut, Leon.
Trying your demo site I noticed that when username is shorter than 6 characters I get an error message but why there are three same messages at a time?

BTW. Posting comments on your site is broken and the links on a page about Flex are broken too. Maybe you could consider changing your website from WP to Drupal? ;-)

Hi!

Thank you for the feedback, I am currently in the middle of a completely new site re-design: http://t.co/WQwYiJUU so all these issues should be fixed soon!

I have not spotted the multiple error messages on the demo, thank you for spotting this, I will take a look, apply a fix and inform you what the problem was and how I fixed it :)

Take care.

Leon.

Hello Again,

What browser are you using to view the demo, I don't seem to be getting the same issue as you. I am getting three different messages, one because the username is too short, one because the first name is too short (Not entered) and thirdly because there is no e-mail entered.

Please let me know if you still get the issue!

Thanks again.

Leon.

Thanks for your prompt reply.
I am using Firefox 17.0.1, but exactly the same situation is in Chrome and IE
These are the messages (Username I enter is less than 6 character long):

There following errors occured:

Your Username must be at least 6 characters in length
Your Username must be at least 6 characters in length
Your Username must be at least 6 characters in length

Try yourself, but enter only one incorrect value at a time. When entering too short Real Name I get the error message twice, when entering incorrect email address I get the error message only once.
Entering all three values incorrect gave me 3 different messages one for each incorrect value, so in this situation it works as expected.

I will take another look. When I tried yesterday I just entered an invalid username (less than 6 characters) and nothing else and got the correct three messages. Will investigate further and get back to you.

Thanks!

Leon Revill.

Hi,

One simple error which I think "EWA" was reffering to...

Need to reset the $msg variable at the begining of the foreach loop (in validate.php) as shown below:

foreach ($inputs as $input) {
			$msg = "";

Thanks for the script!!!

Thanks!

I could never re-produce the error, odd as to why not.

Thank you for that correction, I will update the demo as soon as possible.

Thank you once more,

Leon.

Thank you.This is very good blog.
I wonder about some subject.Can we store the successful data that is coming from the Ajax with Json?Or is there any way to store the data in Php?

Great tut, I´m trying to understand everything step by step becasuse this is a new different way to work with forms to me.

That´s why I have this question: I added 2 new fields "password" and "confirm password", how can I compare those values? I mean, in a common way I could just take the values of the fields with $_POST[] and compare, but I don´t know what to do it in this tut.

Is there any way of compare the values doing a 'case "password" ' and 'case "confirm password" ' or something in the same way the tutorial is made ?

Thanks, and sorry if I didn´t explain enough my question.

Great form. My question is how would you send this form to a thank you page instead of having it load the response div?

Thanks

I found your tutorial most enlightening. Can you detail how to cull and post drop down enumerated data to the db?

As I have seen in demo, when error message come,float up and down slightly. So is it possible to apply animate with loader when ajax content load?

Post new comment