Introduction
The code in this tip shows a simple implementation of table sorting and paging in an ASP.NET MVC application.
Background
In an ASP.NET web form application, GridView
server control can be used to work with a table. GridView
has sorting and paging functions. Although ASP.NET MVC doesn't have any server control, similar functions can be implemented by other frameworks such as jQuery Plugins. Another alternative is to develop custom code by hand. This approach is very beneficial to learning.
Using the Code
There are several ways to implement table sorting and paging. In this simple implementation, the data source of the table is retrieved by an Ajax call to an MVC controller action. The data source is stored in a JavaScript global variable as an array for sorting and paging operation. To sort the table, sort the array and then render the table. The paging also works with the global array variable. In this design, there is only one initial server call to download the data source to the client. Then the sorting and paging are all client side JavaScript manipulation.
First, create an MVC controller and add the following functions:
public ActionResult GetAllProducts()
{
var products = _db.Products
.Select(p => new { p.ProductID, p.ProductName, p.QuantityPerUnit, p.UnitPrice, p.UnitsInStock })
.OrderBy(p => p.ProductID);
return Json(products, JsonRequestBehavior.AllowGet);
}
Second, create a view and add the following markup:
<div>
<table id="tblProducts" class="simpleTable">
<tr>
<th><a id="lnkProductID" href="#">Product ID</a></th>
<th><a id="lnkProductName" href="#">Product Name</a></th>
<th>Quantity Per Unit</th>
<th>Unit Price</th>
<th>Units In Stock</th>
</tr>
</table>
</div>
Last, add some JavaScript code to the view page to implement sorting, paging and table display.
This is the first part of the script.
var tableData = null;
$(document).ready(function () {
$.getJSON('/Home/GetAllProducts', function (data) {
PopulateTable(data, 1);
tableData = data.slice(0);
}).fail(function (jqXHR, textStatus, errorThrown) {
alert('Error getting products!');
});
$('#lnkProductID').click(function (e) {
e.preventDefault();
if (tableData != null) {
tableData.sort(function (a, b) {
return a.ProductID <= b.ProductID ? -1 : 1;
});
PopulateTable(tableData, 1);
}
});
$('#lnkProductName').click(function (e) {
e.preventDefault();
if (tableData != null) {
tableData.sort(function (a, b) {
return a.ProductName <= b.ProductName ? -1 : 1;
});
PopulateTable(tableData, 1);
}
});
});
In the above code, links in table header row are used to initiate table sort. When a link is clicked, the data source is sorted by JavaScript function sort
. The table is rendered by calling function PopulateTable
.
This is the second part of the script for function PopulateTable
.
function PopulateTable(arrData, pageNum) {
var rowsPerPage = 10;
var pages;
var i;
var pager = '';
var startIndex;
var endIndex;
var row;
$('#tblProducts tr:gt(0)').remove();
if (arrData != null) {
startIndex = (pageNum - 1) * rowsPerPage;
endIndex = pageNum * rowsPerPage > arrData.length ?
arrData.length - 1 : pageNum * rowsPerPage - 1;
for (i = startIndex; i <= endIndex; i++) {
row = '<tr><td>' + arrData[i].ProductID + '</td>'
+ '<td>' + arrData[i].ProductName + '</td>'
+ '<td>' + arrData[i].QuantityPerUnit + '</td>'
+ '<td>' + arrData[i].UnitPrice + '</td>'
+ '<td>' + arrData[i].UnitsInStock + '</td></tr>';
$('#tblProducts').append(row);
}
pages = Math.floor(arrData.length / rowsPerPage);
if (pages < arrData.length / rowsPerPage) {
pages += 1;
}
if (pages > 1) {
for (i = 0; i < pages; i++) {
if (i == pageNum - 1) {
pager += '<span>' + (i + 1) + '</span>';
}
else {
pager += '<span><a href="#">' + (i + 1) + '</a></span>'
}
}
pager = '<tr><td colspan="5" class="pagerRow">' +
pager + '</td></tr>';
$('#tblProducts').append(pager);
$('#tblProducts tr td.pagerRow a').click(function (e) {
e.preventDefault();
var pNum = parseInt($(this).text());
PopulateTable(tableData, pNum);
});
}
}
}
This function renders the table from data source parameter arrData
. The page number to render is indicated by parameter pageNum
. The function populates table with only one page. At the last row, it renders a pager. Each page number is a link except current page number. At the end of the function, the event handler of each pager link is defined which basically renders table data of the clicked page number.
Points of Interest
JavaScript library jQuery can greatly simplify HTML manipulation. It is an amazing framework!