Ajax Project - A Sortable Data Grid

Didn't find what you want? Try our search

The projects and demos in this section all use a MySQL database which holds a single table contact with records from a simplified contact manager application.

HTML tables are very limited in their abilities - we can't drag columns around, scroll through the data, or use any of the other facilities we have become used to in the data grids of desktop applications. Of all these shortcomings, perhaps the most significant for most people is the ability to sort data by ordering the grid using a particular column. This project combines Javascript, PHP and Ajax techniques to allow exactly that. Because the server is queried each time a sort is carried out, this technique could be extended to large datasets, unlike the traditional Javascript data grids, which need to load all the data when the page loads.

The grid below can be sorted by column using the up and down arrows.

Each time an arrow is clicked, another request is made of the server, and the data is returned by the server in the order requested.

Try changing the column sort orders. Note that the table is updated each time without the requirement for a page refresh.

 Contact ID   Contact Name   Salut   Telephone 

How It Works

First, let's look at the code behind the grid itself. The grid is actually a straightforward HTML table (well, two tables actually, one for the header and one for the body), with the header made up of the usual <th> tags, and the body wrapped inside a <div>:

<table cellspacing="0" cellpadding="0" style="width:510px"> <tr> <th style="width: 100px;"><img id="up1" src="up.gif" onClick = "getagents('ContactID','');clearimgs();setupimg('up1');">&nbsp; Contact ID&nbsp;<img id="down1" src="down.gif" onClick = "getagents('ContactID','desc');clearimgs();setdownimg('down1');"> </th> <th style="width: 150px"><img id="up2" src="up.gif" onClick = "getagents('ContactFullName','');clearimgs();setupimg('up2');">&nbsp; Contact Name&nbsp;<img id="down2" src="down.gif" onClick = "getagents('ContactFullName','desc');clearimgs();setdownimg('down2');"> </th> <th style="width:110px"><img id="up3" src="up.gif" onClick = "getagents('ContactSalutation','');clearimgs();setupimg('up3');">&nbsp; Salut&nbsp;<img id="down3" src="down.gif" onClick = "getagents('ContactSalutation','desc');clearimgs();setdownimg('down3');"> </th> <th style="width: 150px"><img id="up4" src="up.gif" onClick = "getagents('ContactTel','');clearimgs();setupimg('up4');">&nbsp; Telephone&nbsp;<img id="down4" src="down.gif" onClick = "getagents('ContactTel','desc');clearimgs();setdownimg('down4');"> </th> </tr> </table> <div id="hiddenDIV" style="visibility:hidden; background-color:white; border: 0px solid black;"></div>

Each header contains, as well as the header title, two images (an 'up' and a 'down' arrow). Each of these images has two possible source files, depending whether it is 'illuminated' or not.

Clicking on any of these arrows first calls the getagents() function, passing to it the name of the database field associated with that column, and an argument to indicate whether to sort the data upwards or downwards in that column. Here's the code for the getagents() function:

var url = "getagents.php?param="; // The server-side scripts function getagents(column,direc) { var myRandom=parseInt(Math.random()*99999999); // cache buster http.open("GET", url + escape(column) + "&dir=" + direc + "&rand=" + myRandom, true); http.onreadystatechange = handleHttpResponse; http.send(null); }

The code to instantiate an XMLHTTPRequest is well covered elsewhere on this site, so we'll not do so again here; suffice to say that http is our already-existing XMLHTTPRequest object.

Here we append to the URL of the server routine parameters indicating the column and direction of our sort request. These are passed to the server routine getagents.php as variables.

The variable myRandom contains a random number which is also appended to the URL as a parameter, and helps us to ensure we receive fresh server data rather than data from our browser's cache. This technique is described elsewhere on the site in the article on Cache Busting with Javascript.

We define the javascript routine which will handle the server's response as handleHttpResponse, but before we look at that' let's see what happens at the server by examining the code for getagents.php:

[ ... DB connection code here ... ] $textout = ""; if(strlen($param)>0){ $result = mysql_query("SELECT * FROM contact ORDER BY $param $dir"); while($myrow = mysql_fetch_array($result)){ $agentid = $myrow["ContactID"]; $agentname = $myrow["ContactFullName"]; $agentsalut = $myrow["ContactSalutation"]; $agentinttel = $myrow["ContactTel"]; $textout .= "<tr><td style=\"width: 89px;padding: 0px 0px 0px 10px;\">".$agentid."</td><td style=\"width: 139px; padding: 0px 0px 0px 10px;\">".$agentname."</td><td style=\"width:99px;padding: 0px 0px 0px 10px;\">".$agentsalut. "</td><td style=\"padding: 0px 0px 0px 10px;\">".$agentinttel. "</td></tr>"; } } else { $textout=""; } echo "<table cellspacing=\"0\" cellpadding=\"0\" style=\"width:510px;\">".$textout."</table>";

Here we perform a SELECT query on the contact table, using the ORDER BY construct to select both the field to sort and the sort direction. The information is processed into HTML code for the table which is to form the 'body' part of our data grid, ready to be written straight into our document. This is handled by our handleHttpResponse() function:

function handleHttpResponse() { if (http.readyState == 4) { document.getElementById("hiddenDIV").style.visibility="visible"; document.getElementById("hiddenDIV").innerHTML=http.responseText; } }

This function takes the generated HTML code (contained in the responseText variable) and applies it to the <div> with id 'hiddenDIV', at the same time making the <div> visible and thus publishing the newly sorted table.

Some helper functions - setupimg(), setdownimg() and clearimgs() are used to redraw the up and down arrows appropriately, with the correct arrow 'illuminated'. The code for these functions:

function clearimgs () { document.getElementById('up1').src = upoff.src; document.getElementById('up2').src = upoff.src; document.getElementById('up3').src = upoff.src; document.getElementById('up4').src = upoff.src; document.getElementById('down1').src = downoff.src; document.getElementById('down2').src = downoff.src; document.getElementById('down3').src = downoff.src; document.getElementById('down4').src = downoff.src; } function setupimg(thisid) { document.getElementById(thisid).src="up1.gif"; } function setdownimg(thisid) { document.getElementById(thisid).src="down1.gif"; }

An extra call to the getagents() function is also made in the body's onLoad() event handler, to correctly set up the table when the page is initially loaded.

This grid could easily be extended to offer paging (i.e. 'Previous' and 'Next' buttons) to allow a user to navigate large data sets without ever having to wait for a page refresh.


Before using any software from this site, please see the Terms



7 Users Online.

All of the code and information on this site is provided free of charge (but without warranty).
If you feel that the site has been useful, you may care to donate a little toward the running of the site and the development of further projects?