AJAX & JSON

 

AJAX

AJAX (Asynchronous JavaScript + XML) allow webpages to send data to and retrieve from a database server asynchronously (in the background) without interfering with the display and behavior of the existing page. Using AJAX, a webpage can change its content in real-time. By using AJAX, we do not have to load a new webpage. Instead, we update the current webpage.

AJAX webpages provide a smoother visual appearance to users, as the webpage does not need to reload. Instead, only those parts of the webpage that need to be updated are changed. The rest of the webpage remains unchanged.

First File (send an AJAX request to read data from a database)

ajax_search.php
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AJAX Example</title>
<script>
async function ajaxListModel(model) 
{
    let url = "ajax_get_one_model.php";   /* name of file to send request to */
    let urlParameters = "model=" + model; /* Construct a url parameter string to POST to fileName */
    
    try
    {
        const response = await fetch(url,
        {
             method: "POST",
             headers: {'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'},
             body: urlParameters
        });

        updateWebpage(await response.text());
    }
    catch (error)
    {
        console.log("Fetch failed: ", error);
    }


    /* use the fetched data to change the content of the webpage */
    function updateWebpage(responseText)
    {
        document.getElementById('model').innerHTML = responseText;
    }
}
</script>
</head>
<body>

<div id="listAllModels">
<select name = 'users' onchange = 'ajaxListModel(this.value)'>
  <option value = "">Select a model</option>
  <option value = "corolla">Corolla</option>
  <option value = "yaris">Yaris</option>
  </select>
</div>
<br>
<div id = 'model'>Model details will be listed here.</div>

</body>
</html>
 

Second File (access the database in response to an AJAX request. Every "echo" in this file will be sent as data to the file that issued the AJAX request.)

ajax_get_one_model.php

WARNING: If a php file is being used to fulfill an AJAX request, then it must not have any sourrounding html tags (such as DOCTYPE, HTHM, HEAD, TITLE or BODY). This can be seen in the example below:

<?php
/* Validate and assign input data */
$model = ltrim(rtrim(filter_input(INPUT_POST, "model", FILTER_SANITIZE_STRING)));
if (empty($model))
{
    echo "Invalid input parameter.";
    exit();
}


/* Include "configuration.php" file */
require_once "configuration.php";


/* Connect to the database */
$dbConnection = new PDO("mysql:host=$dbHost;dbname=$dbName", $dbUsername, $dbPassword);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);   // set the PDO error mode to exception


/* Perform query */
$query = "SELECT id, model, colour, year, price FROM toyota WHERE model = :model";
$statement = $dbConnection->prepare($query);
$statement->bindParam(":model", $model, PDO::PARAM_STR);         
$statement->execute();



/* Manipulate the query result */
if ($statement->rowCount() > 0)
{
    echo "<table>";
    $result = $statement->fetchAll(PDO::FETCH_OBJ);
    foreach ($result as $row)
    {
        echo "<tr>";
        echo "<td>" . $row->model . "</td><td>" . $row->colour . "</td><td>" . $row->year . "</td><td>" . $row->price . "</td><td>" . $row->id . "</td>";
        echo "</tr>";
    }
    echo "</table>";
}
echo "<p>" . $statement->rowCount() . " records found.</p>";



/* Provide a link for the user to proceed to a new webpage or automatically redirect to a new webpage */
/* This webpage never actually displays. Instead, it runs in the background on the server. */
/* The "echo" data is automatically sent back inside the "http_request.responseText" of the calling function. */
/* Therefore, no feedback or way to proceed is necessary. */
?>

AJAX allows us to update a webpage without leaving the webpage. This feature is used a lot in modern websites. List various examples of where AJAX is used.

In the example above, the models listed in the drop-down list are hard coded as 'corolla' and 'yaris'. Write php code to create the drop-down list of available models from the database.

Solution php file for the above question:

model_list.php
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>AJAX Example</title>
        <script>
            async function ajaxListModel(model)
            {
                let url = "ajax_get_one_model.php";   /* name of file to send request to */
                let urlParameters = "model=" + model; /* Construct a url parameter string to POST to fileName */

                try
                {
                    const response = await fetch(url,
                            {
                                method: "POST",
                                headers: {'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'},
                                body: urlParameters
                            });

                    updateWebpage(await response.text());
                }
                catch (error)
                {
                    console.log("Fetch failed: ", error);
                }


                /* use the fetched data to change the content of the webpage */
                function updateWebpage(responseText)
                {

                    document.getElementById('model').innerHTML = responseText;
                }
            }



            // All of the black bold text below is the same for both AJAX functions
            async function ajaxListAllModels()
            {
                let url = "ajax_get_all_models.php";   /* name of file to send request to */
                let urlParameters = ""; /* Construct a url parameter string to POST to fileName */

                try
                {
                    const response = await fetch(url,
                            {
                                method: "POST",
                                headers: {'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'},
                                body: urlParameters
                            });

                    updateWebpage(await response.text());
                }
                catch (error)
                {
                    console.log("Fetch failed: ", error);
                }


                /* use the fetched data to change the content of the webpage */
                function updateWebpage(responseText)
                {
                    document.getElementById('listAllModels').innerHTML = responseText;
                }
            }
        </script>
    </head>

    <body onload="ajaxListAllModels();">

        <div id="listAllModels"></div>
        <br>
        <div id = 'model'>Model details will be listed here.</div>

    </body>
</html>




ajax_get_all_models.php
<?php
/* Include "configuration.php" file */
require_once "configuration.php";


/* Connect to the database */
$dbConnection = new PDO("mysql:host=$dbHost;dbname=$dbName", $dbUsername, $dbPassword);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);   // set the PDO error mode to exception


/* Perform query */
/* SELECT DISTINCT ensures that no duplicate model names are selected */
$query = "SELECT DISTINCT model FROM toyota";
$statement = $dbConnection->prepare($query);
$statement->execute();



/* Manipulate the query result */
if ($statement->rowCount() > 0)
{
    $result = $statement->fetchAll(PDO::FETCH_OBJ);

    // create the <select> element with an <option> element for each car model 
    echo '<select name = "users" onchange = "ajaxListModel(this.value)">';
    echo "<option value=''>Select a model</option>";
    foreach ($result as $row)
    {
        echo "<option value='" . $row->model . "'>" . $row->model . "</option>";
    }
    echo "</select>";
}
?>

 

JSON

In our examples above, the php files "ajax_get_one_model.php" and "ajax_get_all_models.php" generate HTML code, which is then inserted into a <DIV> element using the innerHTML() function. The problem with this is that we are mixing the model (database data) with the view (HTML code). This leads to code that is difficult to maintain or reuse.

JSON (JavaScript Object Notation) files allow data to be stored as a string. We can use JSON to pass data back from an AJAX request. Returning the data as a JSON string means that we can generate the HTML code after we get the data from the database code. JSON can be used to remove all php code from the client-side HTML file. This makes our code much cleaner, as we totally separate the data from the view.

The code below uses JSON .

First File (sends two different AJAX requests to read data from a database and process the returned JSON strings)

ajax_json_search.html (note that this can now be a HTML file rather than a PHP file)
<!DOCTYPE html>
<html>
<head>
<title>AJAX JSON search Example</title>
<script>
    async function ajaxListAllModels()
    {
        let url = "ajax_get_all_models.php";   /* use POST method to send data to ajax_json_search.php */
        let urlParameters = "";   /* Construct a url parameter string to POST to fileName */

        try
        {
            const response = await fetch(url,
            {
                method: "POST",
                headers: {'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'},
                body: urlParameters
            });

            updateWebpage(await response.json()); // return a JSON string
        }
        catch (error)
        {
            console.log("Fetch failed: ", error);
        }


        /* use the fetched data to change the content of the webpage */
        function updateWebpage(jsonData)
        {
            let htmlString = "<select name = 'users' onchange = 'ajaxListModel(this.value)'>";

            for (let i = 0; i < jsonData.length; i++)
            {
                htmlString += "<option value='" + jsonData[i].model + "'>" + jsonData[i].model + "</option>";
            }
            htmlString += "</select>";
            
            document.getElementById('allModels').innerHTML = htmlString;
        }
    }


    async function ajaxListModel(model)
    {
        let url = "ajax_get_one_model.php";    /* use POST method to send data to ajax_json_search.php */
        let urlParameters = "model=" + model;  /* Construct a url parameter string to POST to fileName */

        try
        {
            const response = await fetch(url,
            {
                method: "POST",
                headers: {'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'},
                body: urlParameters
            });

            updateWebpage(await response.json());
        }
        catch (error)
        {
            console.log("Fetch failed: ", error);
        }


        /* use the fetched data to change the content of the webpage */
        function updateWebpage(jsonData)
        {
            let htmlString = "<table>";

            for (let i = 0; i < jsonData.length; i++)
            {
                htmlString += "<tr><td>" + jsonData[i].model + "</td><td>" + jsonData[i].colour + "</td><td>" + jsonData[i].year + "</td><td>" + jsonData[i].price + "</td></tr>";
            }
            
            htmlString += "</table><br>" + jsonData.length + " records found.";
            document.getElementById('model').innerHTML = htmlString;
        }
    }
</script>
</head>
<body onload="ajaxListAllModels()">

<div id="allModels"></div><br>
<div id = "model">Model details will be listed here.</div>

</body>
</html>

Second File (get the list of models from the database)

ajax_get_all_models.php

WARNING: If a php file is being used to fulfill an AJAX request, then it must not have any sourrounding html tags (such as DOCTYPE, HTHM, HEAD, TITLE or BODY). This can be seen in the example below:

<?php
/* Include "configuration.php" file */
require_once "configuration.php";


/* Connect to the database */
$dbConnection = new PDO("mysql:host=$dbHost;dbname=$dbName", $dbUsername, $dbPassword);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);   // set the PDO error mode to exception


/* Perform query */
$query = "SELECT DISTINCT model FROM toyota";
$statement = $dbConnection->prepare($query);       
$statement->execute();


/* Manipulate the query result */
$json = "[";
if ($statement->rowCount() > 0)
{
    /* Get field information for all fields */
    $isFirstRecord = true;
    $result = $statement->fetchAll(PDO::FETCH_OBJ);
    foreach ($result as $row)
    {
        if(!$isFirstRecord)
        {
            $json .= ",";
        }
        
        /* NOTE: json strings MUST have double quotes around the attribute names, as shown below */
        $json .= '{"model":"' . $row->model . '"}';
        
        $isFirstRecord = false;
    }  
}     
$json .= "]";

/* Send the $json string back to the webpage that sent the AJAX request */
echo $json;




/* Provide a link for the user to proceed to a new webpage or automatically redirect to a new webpage */
/* This webpage never actually displays. Instead, it runs in the background on the server. */
/* The data contained in the line of code "echo $json;" is automatically sent back inside the "http_request.responseText" of the calling function. */
/* Therefore, no feedback or way to proceed is necessary. */
?>

Third File (get the list of all cars of a particular model from the database)

ajax_get_one_model.php

WARNING: If a php file is being used to fulfill an AJAX request, then it must not have any sourrounding html tags (such as DOCTYPE, HTHM, HEAD, TITLE or BODY). This can be seen in the example below:

<?php
/* Validate and assign input data */
$model = ltrim(rtrim(filter_input(INPUT_POST, "model", FILTER_SANITIZE_STRING)));
if (empty($model))
{
    echo "[]"; // send back an empty JSON string
    exit();
}


/* Include "configuration.php" file */
require_once "configuration.php";


/* Connect to the database */
$dbConnection = new PDO("mysql:host=$dbHost;dbname=$dbName", $dbUsername, $dbPassword);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);   // set the PDO error mode to exception


/* Perform query */
$query = "SELECT id, model, colour, year, price FROM toyota WHERE model = :model";
$statement = $dbConnection->prepare($query);
 $statement->bindParam(":model", $model, PDO::PARAM_STR);        
$statement->execute();



/* Manipulate the query result */
$json = "[";
if ($statement->rowCount() > 0)
{
    /* Get field information for all fields */
    $isFirstRecord = true;
    $result = $statement->fetchAll(PDO::FETCH_OBJ);
    foreach ($result as $row)
    {
        if(!$isFirstRecord)
        {
            $json .= ",";
        }
        
        /* NOTE: json strings MUST have double quotes around the attribute names, as shown below */
        $json .= '{"model":"' . $row->model . '","colour":"' . $row->colour  . '","year":' . strval($row->year)  . ',"price":' . strval($row->price)  . '}';
        
        $isFirstRecord = false;
    }  
}     
$json .= "]";

/* Send the $json string back to the webpage that sent the AJAX request */
echo $json;




/* Provide a link for the user to proceed to a new webpage or automatically redirect to a new webpage */
/* This webpage never actually displays. Instead, it runs in the background on the server. */
/* The data contained in the line of code "echo $json;" is automatically sent back inside the "http_request.responseText" of the calling function. */
/* Therefore, no feedback or way to proceed is necessary. */
?>

Using JSON allows programmers to format the returned data at the client side. This makes the code more maintainable. Place the output from the above example into a "ul" list instead of a "table".

Using JSON means that the view of the data is seperated from the actual data. This means that different files can use the data in different ways. Write code in a new file that only displays the model, year and price of a car.

Post JSON Data to PHP File

We can use the AJAX fetch() method to POST url parameters as a json string to a php or other file.

post_json.php
<!DOCTYPE html>
<html>
    <head>
        <title>AJAX JSON search Example</title>
        <script>
            async function ajaxListAllModels()
            {
                let url = "ajax_get_all_models.php";   /* use POST method to send data to ajax_json_search.php */
                let urlParameters = "";   /* Construct a url parameter string to POST to fileName */

                try
                {
                    const response = await fetch(url,
                            {
                                method: "POST",
                                headers: {'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'},
                                body: urlParameters
                            });

                    updateWebpage(await response.json());
                }
                catch (error)
                {
                    console.log("Fetch failed: ", error);
                }


                /* use the fetched data to change the content of the webpage */
                function updateWebpage(jsonData)
                {
                    let htmlString = "<select name = 'users' onchange = 'ajaxListModel(this.value)'>";
                    for (let i = 0; i < jsonData.length; i++)
                    {
                        htmlString += "<option value='" + jsonData[i].model + "'>" + jsonData[i].model + "</option>";
                    }
                    htmlString += "</select>";

                    document.getElementById('listOfModels').innerHTML = htmlString;
                    ajaxListModel(jsonData[0].model);
                }
            }


            async function ajaxListModel(model)
            {
                let url = "post_json_transaction.php";    /* use POST method to send data to ajax_json_search.php */
                let jsonParameters = {model: model};

                try
                {
                    const response = await fetch(url,
                            {
                                method: "POST",
                                headers: {'Accept': 'application/json', 'Content-Type': 'application/json'},
                                body: JSON.stringify(jsonParameters)
                            });

                    updateWebpage(await response.json());
                }
                catch (error)
                {
                    console.log("Fetch failed: ", error);
                }


                /* use the fetched data to change the content of the webpage */
                function updateWebpage(jsonData)
                {
                    let htmlString = "<table>";

                    for (let i = 0; i < jsonData.length; i++)
                    {
                        htmlString += "<tr><td>" + jsonData[i].model + "</td><td>" + jsonData[i].colour + "</td><td>" + jsonData[i].year + "</td><td>" + jsonData[i].price + "</td></tr>";
                    }

                    htmlString += "</table><br>" + jsonData.length + " records found.";
                    document.getElementById('model').innerHTML = htmlString;
                }
            }
        </script>
    </head>
    <body onload="ajaxListAllModels()">

        <div id="listOfModels"></div><br>
        <div id = "model">Model details will be listed here.</div>

    </body>
</html>
post_json_transaction.php
<?php
header("Content-Type: application/json; charset=UTF-8");

/* read the json data that was sent to this file */
$jsonData = json_decode(file_get_contents('php://input'), true);

/* Validate and assign input data */
$model = $jsonData['model'];  // read the model data from jsonData
if (empty($model)) 
{
    echo "[]"; // send back an empty JSON string
    exit();
}


/* Include "configuration.php" file */
require_once "configuration.php";


/* Connect to the database */
$dbConnection = new PDO("mysql:host=$dbHost;dbname=$dbName", $dbUsername, $dbPassword);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);   // set the PDO error mode to exception


/* Perform query */
$query = "SELECT id, model, colour, year, price FROM toyota WHERE model = :model";
$statement = $dbConnection->prepare($query);
$statement->bindParam(":model", $model, PDO::PARAM_STR);
$statement->execute();



/* Manipulate the query result */
$json = "[";
if ($statement->rowCount() > 0) {
    /* Get field information for all fields */
    $isFirstRecord = true;
    $result = $statement->fetchAll(PDO::FETCH_OBJ);
    foreach ($result as $row) {
        if (!$isFirstRecord) {
            $json .= ",";
        }

        /* NOTE: json strings MUST have double quotes around the attribute names, as shown below */
        $json .= '{"model":"' . $row->model . '","colour":"' . $row->colour . '","year":' . strval($row->year) . ',"price":' . strval($row->price) . '}';

        $isFirstRecord = false;
    }
}
$json .= "]";

/* Send the $json string back to the webpage that sent the AJAX request */
echo $json;




/* Provide a link for the user to proceed to a new webpage or automatically redirect to a new webpage */
/* This webpage never actually displays. Instead, it runs in the background on the server. */
/* The data contained in the line of code "echo $json;" is automatically sent back inside the "http_request.responseText" of the calling function. */
/* Therefore, no feedback or way to proceed is necessary. */
?>
 
<div align="center"><a href="../versionC/index.html" title="DKIT Lecture notes homepage for Derek O&#39; Reilly, Dundalk Institute of Technology (DKIT), Dundalk, County Louth, Ireland. Copyright Derek O&#39; Reilly, DKIT." target="_parent" style='font-size:0;color:white;background-color:white'>&nbsp;</a></div>