Sortable GridView using jQuery’s TableSorter
Introduction
This blog post explains how to use jQuery’s plugin Tablesorter to implement client side sorting in ASP.Net Gridview. This comes in handy especially when object data source is used with grid view as gridview does not provide sorting out of the box
Implementation
To implement TableSorter, the rendered table should have THEAD in the markup. Gridview does not provide this by default but we could achieve it either by setting appropriate properties or by using a CSS friendly control adapter. We will do it by using the former method.
Sample
You could have a look at it online here http://ponnu.net/TableSorter
Using the code
We should get the table with THEAD tags for the gridview to implement the sorting. So, lets do that
- protected void Page_Load(object sender, EventArgs e)
-
{
-
if (this.gvEmployees.Rows.Count > 0)
-
{
-
gvEmployees.UseAccessibleHeader = true;
-
gvEmployees.HeaderRow.TableSection = TableRowSection.TableHeader;
-
gvEmployees.FooterRow.TableSection = TableRowSection.TableFooter;
-
}
-
}
If you are using grid view in update panel and binding it in a call back, then it’s better to put it in gridview’s databound event,
- protected void gvEmployees_DataBound(object sender, EventArgs e)
-
{
-
if (this.gvEmployees.Rows.Count > 0)
-
{
-
gvEmployees.UseAccessibleHeader = true;
-
gvEmployees.HeaderRow.TableSection = TableRowSection.TableHeader;
-
gvEmployees.FooterRow.TableSection = TableRowSection.TableFooter;
-
}
-
}
Now download and include the jQuery and TableSorter js files as follows
Initialize the table for sorting when document is ready using the below code,
-
$(document).ready(function()
-
{
-
$(“#gvEmployees”).tablesorter();
-
});
If you are using update panel, you need to consider using pageLoad function(javascript)
-
function pageLoad(sender, args)
-
{
-
$(“#gvEmployees”).tablesorter();
-
}
At this point the sorting should work on client side, Now you would want to set ascending and descending icons for grid headers. You could easily do this by defining these styles in your style sheet.
-
.headerSortUp
-
{
-
background-position:top;
-
background-repeat: no-repeat;
-
background-image: url(../images/icons/sort_up.gif);
-
background-color: #e9e7d7;
-
}
-
.headerSortDown
-
{
-
background-position:top;
-
background-repeat: no-repeat;
-
background-image: url(../images/icons/sort_down.gif);
-
background-color: #e9e7d7;
-
}
Or you could use the styles that comes with Tablesorter as follows, just set the gridView cssclassname to tablesorter
gvEmployees.CssClass = “tablesorter”;
and include the stylesheet as follows
Tablesorter provides lots of config options, here are few important ones,
sortList: [0, 1] — This instructs to sort by index 0 column in descending order.
dateFormat: “uk” — if your format is dd/MM/yyyy, it does not seem to work by default for this format.
debug: true — this option provides you information like how much time it took and how(what type) it considered the columns.
-
$(“#gvEmployees”).tablesorter(
-
{
-
debug: true, //provides debugging information
-
sortList: [[0, 1]], //sorts 0th column by descending order
-
dateFormat: “uk”, //sets the date format to dd/MM/yyyy
-
});
Now some interesting things, if you have columns that are formatted differently like having a thousand separator. We could use a customParser in this scenario, otherwise the data would be considered string and the sorting would not work as expected.
We should define a customParser with an id and then assign it to a column while initializing tablesorter.
-
//define a parser
-
$.tablesorter.addParser(
-
{
-
// set a unique id
-
id: ‘formattedNumbers’,
-
is: function(s)
-
{
-
// return false so this parser is not auto detected
-
return false;
-
},
-
-
format: function(s)
-
{
-
// format your data for normalization
-
return s.replace(/,/g, ”); //removes comma separator from formatted numbers
-
},
-
// set type, either numeric or text
-
type: ‘numeric’
-
});
-
-
//initialize table for sorting
-
$(“#gvEmployees”).tablesorter(
-
{
-
headers:
-
{
-
6: { sorter: ‘formattedNumbers’ }
-
}
-
})
There might be templated columns and checkbox bound fields in the gridview and if we need to do sorting for those columns, we could do so by using textExtraction. textExtraction is similar to customParser but this applies to the whole table and gets node instead of a string for processing. Here is some code that will process templated text columns and checkbox bound columns.
-
//define a function for extracting text from node
-
function extractValue(node)
-
{
-
var children = node.childNodes[0].childNodes.length
-
-
if (children == 0) //boundTextField or a templateColumn
-
{
-
if (node.childNodes[0].nodeType == 3)//boundTextField
-
{
-
return node.childNodes[0].data;
-
}
-
else //template column
-
{
-
var type = node.childNodes[0].type
-
switch (type) {
-
case “checkbox”:
-
return node.childNodes[0].checked.toString();
-
-
case “radio”:
-
return node.childNodes[0].checked.toString();
-
-
case “text”:
-
return node.childNodes[0].value;
-
-
default: return “”
-
}
-
}
-
}
-
else //boundCheckboxColumn or a templateLabelColumn
-
{
-
if (node.childNodes[0].childNodes[0].nodeType == 3)
-
{
-
return node.childNodes[0].childNodes[0].data;
-
}
-
else
-
{
-
return node.childNodes[0].childNodes[0].checked.toString();
-
}
-
}
-
}
-
-
$(“#gvEmployees”).tablesorter(
-
{
-
textExtraction: extractValue
-
});
This covers most of things that one would do in gridview. The download contains all the above mentioned code.
Points of Interest
The Tablesorter is very good for the kind of functionality it provides with so much less code & effort. I am sure more and more people would be interested in this and would be using this as Microsoft recently announced it’s support to jQuery
It’s very simple to create an extended gridview control built with these functionalities.
You could download the sourcecode for sample from here Download
Ponnu
css classes are not applying
[...] that will move the header row from the TBODY into the THEAD. You can do this on the server using these instructions … Or, you could do it on the client using jQuery’s DOM manipulation API like so … // [...]
Hi Soma,
Can you let me know what css are not applying?
css is not applying for th tag as in your page source
Hi,
Table sorting works great for non integer columns, but for integer it sorts by considering it as string value, is there any way to do integer, decimal sorting using table sorter.
Hi Mohana
Table sorter works for integer and decimal columns also. You could see it working in the sample here http://ponnu.net/TableSorter/ for vacation hours column. Make sure to handle if the numbers are formatted using a custom parser as described in the post above.
If you are doing server side paging, it doesn’t persist the state of the last sort expression.
Do you know how to add that?
Hi T,
You could use a hidden variable to store the sort expression and use that to initialize sorter. Here is the code(I have not tested this)
Table sorter init code
$(“#gvEmployees”).tablesorter(
{
sortList: [[parseInt($("#hfSortDetails").val().split(";")[0]), parseInt($(“#hfSortDetails”).val().split(“;”)[1])]]//sort expression
});
capture the sort details in the sortEnd event
$(“#gvEmployees”).bind(“sortEnd”,function() {$(“#hfSortDetails”).val(this.config.sortList[0][0].toString() + “;” + this.config.sortList[0][1].toString());});
Alternatively, you could extend the table sorter.
This code does not work with .net 2005. Any idea?
Hi Rash,
Can you do a view source on your aspx page and see if the THEAD tags are getting generated, if they are generated make sure you have initialized the table sorter properly.
If you still have the problem please post the code your are trying or email me(using the contact page), I would be glad to assist.
Ponnu
Hi Ponnu,
This code does not work with .net 2008. The THEAD tags doesn’t generate when I do the view source. Do you have any idea?
Thank you
Hi Nhi,
Can you make sure you have the appropriate gridview setting in page load(gridview.UseAccessibleHeader and gridview.HeaderRow.TableSection) and is being executed. I doubt if the VS 2008 will make a difference as this should work in .NET 2.0 and .NET 3.5 also. Or try setting the properties in gridview preRender method.
Alternatively you could use jQuery on client side to generate THEAD tags.
Ponnu
It works now. Thank you
Hi Ponnu,
How do you save the setting of sortable position to the database by using JQuery? For example: We drag item 1 from position 1 to position 2. Is there anyway that JQuery generate the function to save the sortable setting?
Thank you,
Nhi
Hi Ponnu,
I have another question. I try to applied sortable – jquery to User Control ascx, it works in IE, but it doesn’t work in Mozilla browser. Do you have any idea?
Thanks in advance
Nhi
Hi Nhi,
>>”How do you save the setting of sortable position to the database by using JQuery? For example: We drag item 1 from position 1 to position 2. Is there anyway that JQuery generate the function to save the sortable setting?”
I guess you are looking at saving the last sorted column with direction to the database and use it when the page is accessed next time. If that’s the case, you will need to save the sort details into a hidden varaiable and save it in database and use that information at later point. You could easily implement by doing similar to this
$(“#gvEmployees”).tablesorter(
{
sortList: [[parseInt($("#hfSortDetails").val().split(";")[0]), parseInt($(”#hfSortDetails”).val().split(”;”)[1])]]//sort expression
});
capture the sort details in the sortEnd event
$(“#gvEmployees”).bind(”sortEnd”,function() {$(”#hfSortDetails”).val(this.config.sortList[0][0].toString() + “;” + this.config.sortList[0][1].toString());});
I have note tested it, but it should work. Make sure you initialise hidden variable for the first time. Alternatively you could extend tablesorter plugin.
>>”I have another question. I try to applied sortable – jquery to User Control ascx, it works in IE, but it doesn’t work in Mozilla browser. Do you have any idea?”
I doubt having the gridview in user control would make a difference in Mozilla, you could check these things to track down the problem,
See if THEAD tags are generated in the source when viewing from mozilla.
And also make sure the table is initialized with the table sorter plugin.
If you are still having problems, send me a sample with the problem I would be glad to assist.
Ponnu
Hi Ponnu,
I have a table gridview and view button on each rows. When I mouseover on each view button, popup panel that displays each user’s information shows up, the panel is gone when mouse out. How do I use Jquery to make that work? Do you have any idea?
Thanks in advance
Nhi
Hi,
Can you please confirm me if the sorting works for a gridview having a column of images.
Images having names say ‘A.gif’ or ‘B.gif’ or ‘C.gif’.
If yes, on what basis this image column will get sorted……..
Thanks
Hi,
How to integrate it with JQuery Paging?
I got the JQuery for paging and added the script given in this article for sorting. But i am getting “Microsoft JScript runtime error: Object doesn’t support this property or method ” error.
Please help me for this problem.
Thanks.
Priyadarsini
And about TableSorter Pager plugin?
@sadhana
Have a look at using parser here – http://tablesorter.com/docs/example-parsers.html
@Priyadarsini
You will have to check the linenumber and see what’s the problem if it’s showing one.
Check and make sure you have specified the correct gridview id for tablesorter and included jQuery and tablesorter js files.
Thanks for this post.
When I sort my “even” and “odd” rows CSS get mixed up and don’t refresh (ending up with two dark rows, then a single light, then one dark, and two light… etc).
The demo’s don’t do this so I’m hoping there’s some easy fix for this.
Hi Ponnu,
I have used TableSorter and JQuery Paging for a gridview. When I sort the data in the table, only current page data is getting sorted. I want to sort on all the data and then display the approriate page data. For eg., user is in 2nd page and sorted on one column, I want to sort on entire data and display the 2nd page data. How to do that?
@Chris,
Sorry for the delayed reply. You could handle the sort event and re-apply the CSS to fix the issue.
Hope it helps others with same issue looking here.
@Surya,
Sorry for the delayed reply. I do not know what jQuery plugin you are using for clientside paging. You could see if the plugin provides any options to sort the data and implement events for the header instead of using tablesorter.