One of my previous article Creating Grid (Table) With Sorting, Filtering and Paging in Asp.Net MVC discussed about displaying tabular data using Grdi.Mvc component with inbuilt support for sorting and paging. When the user clicks the column header the actual sorting is done in server side when using Grid.Mvc control. In this article, let’s implement a client sorting on the html table without a post back. We will use a jQuery plugin called tablesorter for doing this.
I will use a simple Employee-Department model with Entity Framework Code First for creating a tabular data in a Asp.Net MVC 5.0 project. Complete source code is attached at the bottom of this article for reference.
First, let us download the table sorter plugin from here and integrate it into our MVC application. Download the latest tablesorter package and unzip it. Copy jquery.tablesorter.min.js, jquery.metadata.js and themes folder into our project Scripts folder like below,
You also need the latest version of jQuery, the tablesorter plugin package already packs a jQuery library you can either use it or get it separately from the jQuery official site. I have already included jQuery and it is linked from layout page.
Let us first build a view to display a list of employees from Employee table. The View and Controller Action method code below,
GetAllEmployeeData.cshtml
@model IEnumerable<GridDemo.Models.Employee>
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>MVC Grid</h2>
<div>
@Html.ActionLink("Index", "Index")
</div>
<div>
<table id="EmployeeList" class="table table-bordered table-condensed">
<thead>
<tr>
<th>Id</th>
<th>First Name</th>
<th>Last Name</th>
<th>Address1</th>
<th>City</th>
<th>State</th>
<th>Country</th>
<th>Postal Code</th>
<th>Salary</th>
<th>Email</th>
<th>Date of Birth</th>
<th>Department</th>
</tr>
</thead>
<tbody>
@foreach (Employee emp in Model)
{
<tr>
<td>@emp.EmployeeId</td>
<td>@emp.FirstName</td>
<td>@emp.LastName</td>
<td>@emp.Address1</td>
<td>@emp.City</td>
<td>@emp.State</td>
<td>@emp.Country</td>
<td>@emp.PostalCode</td>
<td>
@if(@emp.Country == "UK")
{
@String.Format(new System.Globalization.CultureInfo("en-GB", false),"{0:C}",emp.Salary)
}
else
{
@String.Format("{0:C}",emp.Salary)
}
</td>
<td>@emp.Email</td>
<td>@emp.DOB</td>
<td>@emp.Department.DepartmentName</td>
</tr>
}
</tbody>
</table>
</div>
Action method
public ActionResult GetAllEmployeeData()
{
return View(db.Employees.Include("Department").OrderBy(e => e.EmployeeId));
}
Integrating TableSorter Plugin
Now, let’s add sorting using table sorter plugin. Link the CSS file and the plugin script file that we copied into the solution in the view.
@section css {
<link rel="stylesheet" href="@Url.Content("~/Scripts/tablesorter/themes/blue/style.css")" />
}
@section scripts {
<script type="text/javascript">
$(document).ready(function () {
$("#EmployeeList").tablesorter();
});
</script>
<script src="@Url.Content("~/Scripts/tablesorter/jquery.tablesorter.min.js")" type="text/javascript"> </script>
}
In _Layout page, I have declared 2 sections using @RenderSection helper methods, one for css and scripts to include stylesheets and scripts from the content view.
Add the css class tablesorter for the table like below,
<table id="EmployeeList" class="table table-bordered table-condensed tablesorter">
Execute the application and you can see the sorting enabled in the table like below. Click the headers to sort the table.
Adding a default sort
We can add a default initial sort using table sorter plugin. The plugin takes an options object as a parameter where we can specify the default sort. The parameter is expressed as [ColumnIndex,SortOrder]. The SortOrder 0 is ascending and 1 is descending. For example, the below script sorts the column at index 0 in ascending order and column at index 2 in descending order.
<script type="text/javascript">
$(document).ready(function () {
$("#EmployeeList").tablesorter({ sortList: [[0, 0], [2, 1]] });
});
</script>
When executed the plugin applies a default initial sort like below,
Disabling Sort on Specific columns
We can disable sorting on specific columns by passing the column index in tablesorter option object. The below script disables the 2nd column and 4th column.
$("#EmployeeList").tablesorter({
sortList: [[0, 0], [2, 1]],
headers: {
1: { sorter: false },
3: {sorter: false }
}
});
When executed, you won’t see the sort working for First Name and Address1 columns like below,
Adding Custom Column Parser to Sort columns with Special Characters
Sometimes, we will have columns with special characters in the text which does not works well with sorting. For example, the Salary column has amount expressed in multiple currencies with currency symbols. When you click the header for sorting, you will see the sort doesn’t work as expected. This is due to the special characters $ and £ symbol.
To manage these types of column, we can a custom column parser which can filter out the special character like above before performing sort. For doing this, we need to include the jquery.metadata.js plugin that comes by default in the download package. The below code helps us to do that,
@section scripts {
<script type="text/javascript">
$(document).ready(function () {
$.tablesorter.addParser({
id: 'money',
is: function (s) {
return false;
},
format: function (s) {
return s.replace('$', '').replace('£', '').replace(/,/g, '');
},
type: 'numeric'
});
$("#EmployeeList").tablesorter({ sortList: [[0, 0], [2, 1]] });
});
</script>
<script src="@Url.Content("~/Scripts/tablesorter/jquery.metadata.js")" type="text/javascript"> </script>
<script src="@Url.Content("~/Scripts/tablesorter/jquery.tablesorter.min.js")" type="text/javascript"> </script>
}
We also need to attach the parser on the table column like below,
<table id="EmployeeList" class="table table-bordered table-condensed tablesorter">
<thead>
<tr>
<th>Id</th>
<th>First Name</th>
<th>Last Name</th>
<th>Address1</th>
<th>City</th>
<th>State</th>
<th>Country</th>
<th>Postal Code</th>
<th class="{sorter: 'money'}">Salary</th>
<th>Email</th>
<th>Date of Birth</th>
<th>Department</th>
</tr>
</thead>
When executed, you can see the sorting works considering it as a numeric field.
Note – There are some inbuilt parsers like text, percent which we can specify on the column headers similar to above. For example,
<tr>
<th class="{sorter: 'text'}">first name</th>
<th>last name</th>
<th>age</th>
<th>total</th>
<th class="{sorter: 'procent'}">discount</th>
<th>date</th>
</tr>
Download the source and see it in action!