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

  1. protected void Page_Load(object sender, EventArgs e)
  2.     {
  3.         if (this.gvEmployees.Rows.Count > 0)
  4.         {
  5.             gvEmployees.UseAccessibleHeader = true;
  6.             gvEmployees.HeaderRow.TableSection = TableRowSection.TableHeader;
  7.             gvEmployees.FooterRow.TableSection = TableRowSection.TableFooter;
  8.         }
  9.     }

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,

  1. protected void gvEmployees_DataBound(object sender, EventArgs e)
  2.     {
  3.         if (this.gvEmployees.Rows.Count > 0)
  4.         {
  5.             gvEmployees.UseAccessibleHeader = true;
  6.             gvEmployees.HeaderRow.TableSection = TableRowSection.TableHeader;
  7.             gvEmployees.FooterRow.TableSection = TableRowSection.TableFooter;
  8.         }
  9.     }

Now download and include the jQuery and TableSorter js files as follows

  1. <script type=“text/javascript” src=“scripts/jquery-latest.js”></script>
  2. <script type=“text/javascript” src=“scripts/jquery.tablesorter.js”></script>

Initialize the table for sorting when document is ready using the below code,

  1. $(document).ready(function()
  2. {
  3.     $(“#gvEmployees”).tablesorter();
  4. });

If you are using update panel, you need to consider using pageLoad function(javascript)

  1. function pageLoad(sender, args)
  2. {
  3.     $(“#gvEmployees”).tablesorter();
  4. }

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.

  1. .headerSortUp
  2. {
  3.     background-position:top;
  4.     background-repeat: no-repeat;
  5.     background-image: url(../images/icons/sort_up.gif);
  6.     background-color: #e9e7d7;
  7. }
  8. .headerSortDown
  9. {
  10.     background-position:top;
  11.     background-repeat: no-repeat;
  12.     background-image: url(../images/icons/sort_down.gif);
  13.     background-color: #e9e7d7;
  14. }

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

<link rel=“stylesheet” type=“text/css” href=“themes/green/style.css” />

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.

  1. $(“#gvEmployees”).tablesorter(
  2. {
  3.     debug: true, //provides debugging information
  4.     sortList: [[0, 1]], //sorts 0th column by descending order
  5.     dateFormat: “uk”, //sets the date format to dd/MM/yyyy
  6. });

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.

  1. //define a parser
  2. $.tablesorter.addParser(
  3. {
  4.     // set a unique id
  5.     id: ‘formattedNumbers’,
  6.     is: function(s)
  7.     {
  8.         // return false so this parser is not auto detected
  9.         return false;
  10.     },
  11.  
  12.     format: function(s)
  13.     {
  14.         // format your data for normalization
  15.         return s.replace(/,/g, ); //removes comma separator from formatted numbers
  16.     },
  17.     // set type, either numeric or text
  18.     type: ‘numeric’
  19. });
  20.  
  21. //initialize table for sorting
  22. $(“#gvEmployees”).tablesorter(
  23. {
  24.     headers:
  25.     {
  26.         6: { sorter: ‘formattedNumbers’ }
  27.     }
  28. }) 

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.

  1. //define a function for extracting text from node
  2. function extractValue(node)
  3. {
  4.     var children = node.childNodes[0].childNodes.length
  5.    
  6.     if (children == 0) //boundTextField or a templateColumn
  7.     {
  8.         if (node.childNodes[0].nodeType == 3)//boundTextField
  9.         {
  10.             return node.childNodes[0].data;
  11.         }
  12.         else //template column
  13.         {
  14.             var type = node.childNodes[0].type
  15.             switch (type) {
  16.                 case “checkbox”:
  17.                     return node.childNodes[0].checked.toString();
  18.  
  19.                 case “radio”:
  20.                     return node.childNodes[0].checked.toString();
  21.  
  22.                 case “text”:
  23.                     return node.childNodes[0].value;
  24.                    
  25.                 default: return “”
  26.             }
  27.         }
  28.     }
  29.     else //boundCheckboxColumn or a templateLabelColumn
  30.     {
  31.         if (node.childNodes[0].childNodes[0].nodeType == 3)
  32.         {
  33.             return node.childNodes[0].childNodes[0].data;
  34.         }
  35.         else
  36.         {
  37.             return node.childNodes[0].childNodes[0].checked.toString();
  38.         }
  39.     }
  40. }
  41.  
  42. $(“#gvEmployees”).tablesorter(
  43. {
  44.     textExtraction: extractValue
  45. })

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

26 Comments

soma sekharOctober 24th, 2008 at 8:39 am

css classes are not applying

iTunes Data Grid Skin @ ZDima.netNovember 2nd, 2008 at 2:25 pm

[...] 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 … //  [...]

PonnuNovember 8th, 2008 at 1:35 am

Hi Soma,
Can you let me know what css are not applying?

somaNovember 26th, 2008 at 10:08 am

css is not applying for th tag as in your page source

Mohana DasariJanuary 28th, 2009 at 12:16 pm

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.

PonnuJanuary 29th, 2009 at 10:52 pm

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.

TFebruary 5th, 2009 at 8:20 pm

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?

PonnuFebruary 5th, 2009 at 9:42 pm

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.

RashApril 6th, 2009 at 6:45 pm

This code does not work with .net 2005. Any idea?

PonnuApril 6th, 2009 at 7:45 pm

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

NhiMay 8th, 2009 at 8:24 pm

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

PonnuMay 11th, 2009 at 10:13 pm

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

NhiMay 12th, 2009 at 6:27 pm

It works now. Thank you

NhiMay 12th, 2009 at 10:21 pm

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

NhiMay 13th, 2009 at 5:07 pm

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

PonnuMay 14th, 2009 at 8:19 am

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

NhiMay 29th, 2009 at 12:50 am

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

sadhanaMay 30th, 2009 at 5:57 pm

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

PriyadarsiniAugust 10th, 2009 at 9:51 am

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

FabioOctober 12th, 2009 at 11:54 pm

And about TableSorter Pager plugin?

PonnuFebruary 14th, 2010 at 9:29 pm

@sadhana

Have a look at using parser here – http://tablesorter.com/docs/example-parsers.html

PonnuFebruary 14th, 2010 at 9:35 pm

@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.

ChrisMay 25th, 2010 at 2:35 pm

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.

SuryaJuly 5th, 2010 at 11:00 am

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?

PonnuAugust 17th, 2010 at 8:40 pm

@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.

PonnuAugust 17th, 2010 at 8:57 pm

@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.

Leave a comment

Your comment

Spam Protection by WP-SpamFree