Introduction to AJAX
I. XMLHttpRequest
AJAX stands for Asynchronous JavaScript and XML. AJAX is a new technique for creating better,
faster, and more interactive web applications with the help of XML, HTML, CSS, and JavaScript.
AJAX uses XHTML for content, CSS for presentation, along with Document Object Model and JavaScript
for dynamic content display.
AJAX allows web pages to be updated asynchronously by exchanging small amounts of data with the
server behind the scenes. This means that it is possible to update parts of a web page, without
reloading the whole page.
AJAX is not a programming language. AJAX is a technique for accessing web servers from a web page.
- An event occurs in a web page (the page is loaded, a button is clicked)
- An XMLHttpRequest object is created by JavaScript
- The XMLHttpRequest object sends a request to a web server
- The server processes the request
- The server sends a response back to the web page
- The response is read by JavaScript
- Proper action (like page update) is performed by JavaScript
In the example below, when a user clicks on the button, the content of the file "My_File.txt" will be loaded into the div element with the id "demo":
JavaScript
<script>
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("GET", "My_File.txt", true);
xhttp.send();
}
</script>
<button type="button" onclick="loadDoc()">Change Content</button>
<div id="demo"></div>
Result
In the example above, the JavaScript function loadDoc() is triggered by the button click.
The function will first create an XMLHttpRequest object (var xhttp = new
XMLHttpRequest();)
The xhttp.onreadystatechange property specifies a function to be executed every time the
readyState
property changes.
The function checks if the readyState property is 4 and the status property is 200. If true, it
will
write the content of the file "My_File.txt" into the div element with the id "demo".
The readyState property holds the status of the XMLHttpRequest. It is an integer from 0 to 4 and
it
is updated by the XMLHttpRequest object when the request is in progress:
- 0: request not initialized
- 1: server connection established
- 2: request received
- 3: processing request
- 4: request finished and response is ready
An HTTP status code is returned by the server in response to the request made by the XMLHttpRequest object.
The status property is an integer from 200 to 599:
- 200: "OK"
- 403: "Forbidden"
- 404: "Page not found"
- The type of request: GET or POST
- The URL of the server the request is sent to
- Optional: true (asynchronous) or false (synchronous)
The responseText property returns the response data as a string.
The responseXML property returns the response data as XML data.
The response property returns the response data.
XMLHttpRequest Object Properties
The following table lists the most important properties of the XMLHttpRequest object:
Property | Description |
---|---|
onload | Defines a function to be called when the request is received (loaded) |
onreadystatechange | Stores a function (or the name of a function) to be called automatically each time the readyState property changes |
readyState | Holds the status of the XMLHttpRequest. Changes from 0 to 4: 0: request not initialized 1: server connection established 2: request received 3: processing request 4: request finished and response is ready |
responseText | Returns the response data as a string |
responseXML | Returns the response data as XML data |
status | Returns the status-number of a request |
statusText | Returns the status-text (e.g. "OK" or "Not Found") |
Bellow is an example of how to use the onload property of the XMLHttpRequest object:
JavaScript
<script>
var xhttp = new XMLHttpRequest();
xhttp.onload = function() {
if (this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("GET", "My_File2.txt", true);
xhttp.send();
</script>
<div id="demo"></div>
Result
In the example above, the onload property is used to define a function to be called when the request
is received.
The function checks if the status property is 200 (OK). If true, it writes the content of the file
"My_File2.txt" into the div element with the id "demo".
XMLHttpRequest Object Methods
The following table lists the most important methods of the XMLHttpRequest object:
Method | Description |
---|---|
abort() | Cancels the current request |
getAllResponseHeaders() | Returns header information |
getResponseHeader() | Returns specific header information |
open(method, url, async, user, psw) | Specifies the type of request: method: GET or POST, url: the server (file) location, async: true (asynchronous) or false (synchronous), user: optional user name, psw: optional password |
send() | Sends the request to the server (used for GET) |
setRequestHeader() | Adds a label/value pair to the header to be sent |
Example
To illustrate the use of AJAX, we will create a simple example that will fetch data from a MySQL
database using PHP. You can find the complete code here.
In the example bellow, we will create a database "ajax_php_example" with a table "product" with the
following structure:
In the index.php file, we put a table that will display the data from the "product" table and a
button to add new products.
We have only declared a table without defining its structure. We will the Read.php file to do that.
<h1>Product List</h1>
<button type="button" class="btn btn-primary" id="Add_Btn">Add </button>
<table class="table table-striped" id="Product_Table">
<?php require_once 'Read.php'; ?>
</table>
In the Read.php file, we will write the PHP code that will fetch the data from the "product" table
and display it in the table.
This code create a table with the headers for the columns and then selects all the data from the
Product table.
An additional column is added to the table for the actions (Edit and Delete).
The Delete button will call the Delete() function with the Product_ID as a parameter.
The Edit button will call the Edit() function with the Product_ID as a parameter.
This is is the easiest way to keep track of the product that we want to edit or delete.
<?php
/*
* This file is used to read data from the database and display it in the table.
* It is included in index.php.
*/
// It start by requiring the Connect.php file to establish a connection to the database.
require_once "Connect.php";
// It then creates a table with the headers for the columns.
echo " <tr>
<th>Product code</th>
<th>Product name</th>
<th>Description</th>
<th>Price</th>
<th>Actions</th>
</tr>";
// It then selects all the data from the Product table.
$sql = "SELECT * FROM Product";
$result = mysqli_query($My_Connection, $sql);
if (mysqli_num_rows($result) > 0) {
while ($row = mysqli_fetch_assoc($result)) {
// It then creates a row for each product in the table.
echo "<tr>";
echo "<td>" . $row["Product_ID"] . "</td>";
echo "<td>" . $row["Product_Name"] . "</td>";
echo "<td>" . $row["Product_Description"] . "</td>";
echo "<td>" . $row["Price"] . "</td>";
echo "<td><button type='button' class='btn btn-danger' onclick='Delete(" . $row["Product_ID"] . ")'>Delete</button>";
echo "<button type='button' class='btn btn-success' onclick='Edit(" . $row["Product_ID"] . ")'>Edit</button></td>";
echo "</tr>";
}
} else {
echo "0 results";
}
When the user clicks on the Add button, a modal will pop up with a form to add a new product.
The form will have fields for the Product Name, Description, and Price.
When the user submits the form, the data will be sent to the server using AJAX.
The data will be sent to the add.php file, which will insert the data into the Product table.
The add.php file will then call the Read.php file to display the updated table.
// We add an event listener to the Add_Form
Add_Form.addEventListener("submit", function (event) {
// We prevent the default behavior of the form
event.preventDefault();
// We create a new XMLHttpRequest object
const xhr = new XMLHttpRequest();
// We open a new POST request to the add.php file
xhr.open("POST", "add.php");
// We set the Content-Type header to "application/x-www-form-urlencoded"
// This header is used to specify the type of data that is being sent to the server
// In this case, we are sending form data to the server in the format of key-value pairs
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// We add an event listener to the xhr object
// This event listener is called every time the readyState property of the xhr object changes
// The readyState property of the xhr object represents the state of the request
// The onreadystatechange event is triggered when the readyState property changes
xhr.onreadystatechange = function () {
// We check if the readyState property is equal to XMLHttpRequest.DONE
// This means that the request has been completed
// We also check if the status property is equal to 200
// This means that the request was successful
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
// If the request was successful,
// we set the innerHTML of the Table element to the responseText of the xhr object
// The xhr.responseText property contains the result of Read.php file since it is called
// at the end of add.php
Table.innerHTML = xhr.responseText;
}
};
// We get the values of the input fields in the Add_Form
// We use the encodeURIComponent function to encode the values
// so that they can be sent as part of the URL
const Product_ID = encodeURIComponent(
document.getElementById("Product_ID").value
);
const Product_Name = encodeURIComponent(
document.getElementById("Product_Name").value
);
const Product_Description = encodeURIComponent(
document.getElementById("Product_Description").value
);
const Price = encodeURIComponent(document.getElementById("Price").value);
// The following are the parameters that will be sent to the server
// They are in the format of key-value pairs
const snd = `Product_ID=${Product_ID}&Product_Name=${Product_Name}&Product_Description=${Product_Description}&Price=${Price}`;
// We send the parameters to the server
xhr.send(snd);
// We hide the Dark_Background and Add_Form
Dark_Background.classList = "Hidden";
Add_Form.classList = "Hidden";
});
In other words, the "Table.innerHTML = xhr.responseText;" will wait untill the file that we called
earlier with the "xhr.open("POST", "add.php");" is done and then take its response (which is
"xhr.responseText") and put it in the
innerHTML of the Table element.
That is why we called Read.php at the end of the add.php file.
<?php
// This file is used to add data to the database.
// It starts by requiring the Connect.php file to establish a connection to the database.
require_once "Connect.php";
// It then checks if the request method is POST.
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// It then gets the data from the form and assigns it to variables.
$Product_ID = $_POST["Product_ID"];
$Product_Name = $_POST["Product_Name"];
$Description = $_POST["Product_Description"];
$Price = $_POST["Price"];
// It then inserts the data into the Product table.
$sql = "INSERT INTO Product (Product_ID, Product_Name, Product_Description, Price) VALUES (?, ?, ?, ?)";
$stmt = mysqli_stmt_init($My_Connection);
if (!mysqli_stmt_prepare($stmt, $sql)) {
echo "SQL statement failed";
} else {
mysqli_stmt_bind_param($stmt, "isss", $Product_ID, $Product_Name, $Description, $Price);
mysqli_stmt_execute($stmt);
}
}
// It then calls the Read.php file to display the updated table.
require_once "Read.php";
For the Edit and Delete functionalities, we will use the same approach.
The only thing that changes in the Edit.php and Delete.php files is the SQL query.