Introduction jQuery enjoys living inside pages which are built on top of ASP.NET MVC Framework.
The ASP.NET MVC is a place where things are organized very well and it is quite hard to make them dirty, especially because
the pattern enforces you on purity (you can still make it dirty if you want so ;) ). We all know how easy is to build a HTML table with a header row, footer row and table rows showing some data. With ASP.NET MVC we can do this pretty easy, but,
the result will be pure HTML table which only shows data, but does not includes sorting, pagination or some other advanced features that we were used to have in
the ASP.NET WebForms GridView. Ok, there is
the WebGrid MVC Helper, but what if we want to make something from pure table in our own clean style? In one of my recent projects, I’ve been using
the jQuery tablesorter and tablesorter.pager plugins that go along. You don’t need to know jQuery to make this work… You need to know little CSS to create nice design for your table, but of course you can use mine from
the demo… So, what you will see in this blog is how to attach this plugin to your pure html table and a div for pagination and make your table with advanced sorting and pagination features. Demo Project Resources
The resources I’m using for this demo project are shown in
the following solution explorer window print screen: Content/images – folder that contains all
the up/down arrow images, pagination buttons etc. You can freely replace them with your own, but keep
the names
the same if you don’t want to change anything in
the CSS we will built later. Content/Site.css –
The main css theme, where we will add
the theme for our table too Controllers/HomeController.cs –
The controller I’m using for this project Models/Person.cs – For this demo, I’m using
Person.cs class Scripts – jquery-1.4.4.min.js, jquery.tablesorter.js, jquery.tablesorter.pager.js – required script to make
the magic happens Views/Home/Index.cshtml – Index view (razor view engine)
the other items are not important for
the demo. ASP.NET MVC 1. Model In this demo I use only one
Person class which defines
Person entity with several properties. You can use your own model, maybe one which will access data from database or any other resource.
Person.cs public class
Person { public string Name { get; set; } public string Surname { get; set; } public string Email { get; set; } public int? Phone { get; set; } public DateTime? DateAdded { get; set; } public int? Age { get; set; } public Person(string name, string surname, string email, int? phone, DateTime? dateadded, int? age) { Name = name; Surname = surname; Email = email; Phone = phone; DateAdded = dateadded; Age = age; } } 2. View In our example, we have only one Index.chtml page where Razor View engine is used. Razor view engine is my favorite for ASP.NET MVC because it’s very intuitive, fluid and keeps your code clean. 3. Controller Since this is simple example with one page, we use one HomeController.cs where we have two methods, one of ActionResult type (Index) and another GetPeople() used to create and return list of people. HomeController.cs public class HomeController : Controller { // // GET: /Home/ public ActionResult Index() { ViewBag.People = GetPeople(); return View(); } public List<Person> GetPeople() { List<Person> listPeople = new List<Person>(); listPeople.Add(new Person("Hajan", "Selmani", "
[email protected]", 070070070,DateTime.Now, 25)); listPeople.Add(new Person("Straight", "Dean", "
[email protected]", 123456789, DateTime.Now.AddDays(-5), 35)); listPeople.Add(new Person("Karsen", "Livia", "
[email protected]", 46874651, DateTime.Now.AddDays(-2), 31)); listPeople.Add(new Person("Ringer", "Anne", "
[email protected]", null, DateTime.Now, null)); listPeople.Add(new Person("O'Leary", "Michael", "
[email protected]", 32424344, DateTime.Now, 44)); listPeople.Add(new Person("Gringlesby", "Anne", "
[email protected]", null, DateTime.Now.AddDays(-9), 18)); listPeople.Add(new Person("Locksley", "Stearns", "
[email protected]", 2135345, DateTime.Now, null)); listPeople.Add(new Person("DeFrance", "Michel", "
[email protected]", 235325352, DateTime.Now.AddDays(-18), null)); listPeople.Add(new Person("White", "Johnson", null, null, DateTime.Now.AddDays(-22), 55)); listPeople.Add(new Person("Panteley", "Sylvia", null, 23233223, DateTime.Now.AddDays(-1), 32)); listPeople.Add(new Person("Blotchet-Halls", "Reginald", null, 323243423, DateTime.Now, 26)); listPeople.Add(new Person("Merr", "South", "
[email protected]", 3232442, DateTime.Now.AddDays(-5), 85)); listPeople.Add(new Person("MacFeather", "Stearns", "
[email protected]", null, DateTime.Now, null)); return listPeople; } } TABLE CSS/HTML DESIGN Now, lets start with
the implementation. First of all, lets create
the table structure and
the main CSS. 1. HTML Structure @{ Layout = null; } <!DOCTYPE html> <html> <head> <title>ASP.NET & jQuery</title> <!-- referencing styles, scripts and writing custom js scripts will go here --> </head> <body> <div> <table class="tablesorter"> <thead> <tr> <th> value </th> </tr> </thead> <tbody> <tr> <td>value</td> </tr> </tbody> <tfoot> <tr> <th> value </th> </tr> </tfoot> </table> <div id="pager"> </div> </div> </body> </html> So, this is
the main structure you need to create for each of your tables where you want to apply
the functionality we will create. Of course
the scripts are referenced once ;). As you see, our table has class tablesorter and also we have a div with id pager. In
the next steps we will use both these to create
the needed functionalities.
The complete Index.cshtml coded to get
the data from controller and display in
the page is: <body> <div> <table class="tablesorter"> <thead> <tr> <th>Name</th> <th>Surname</th> <th>Email</th> <th>Phone</th> <th>Date Added</th> </tr> </thead> <tbody> @{ foreach (var p in ViewBag.People) { <tr> <td>@p.Name</td> <td>@p.Surname</td> <td>@p.Email</td> <td>@p.Phone</td> <td>@p.DateAdded</td> </tr> } } </tbody> <tfoot> <tr> <th>Name</th> <th>Surname</th> <th>Email</th> <th>Phone</th> <th>Date Added</th> </tr> </tfoot> </table> <div id="pager" style="position: none;"> <form> <img src="@Url.Content("~/Content/images/first.png")" class="first" /> <img src="@Url.Content("~/Content/images/prev.png")" class="prev" /> <input type="text" class="pagedisplay" /> <img src="@Url.Content("~/Content/images/next.png")" class="next" /> <img src="@Url.Content("~/Content/images/last.png")" class="last" /> <select class="pagesize"> <option selected="selected" value="5">5</option> <option value="10">10</option> <option value="20">20</option> <option value="30">30</option> <option value="40">40</option> </select> </form> </div> </div> </body> So, mainly
the structure is
the same. I have added @Razor code to create table with data retrieved from
the ViewBag.People which has been filled with data in
the home controller. 2. CSS Design
The CSS code I’ve created is: /* DEMO TABLE */ body { font-size: 75%; font-family: Verdana, Tahoma, Arial, "Helvetica Neue", Helvetica, Sans-Serif; color: #232323; background-color: #fff; } table { border-spacing:0; border:1px solid gray;} table.tablesorter thead tr .header { background-image: url(images/bg.png); background-repeat: no-repeat; background-position: center right; cursor: pointer; } table.tablesorter tbody td { color: #3D3D3D; padding: 4px; background-color: #FFF; vertical-align: top; } table.tablesorter tbody tr.odd td { background-color:#F0F0F6; } table.tablesorter thead tr .headerSortUp { background-image: url(images/asc.png); } table.tablesorter thead tr .headerSortDown { background-image: url(images/desc.png); } table th { width:150px; border:1px outset gray; background-color:#3C78B5; color:White; cursor:pointer; } table thead th:hover { background-color:Yellow; color:Black;} table td { width:150px; border:1px solid gray;} PAGINATION AND SORTING Now, when everything is ready and we have
the data, lets make pagination and sorting functionalities 1. jQuery Scripts referencing <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" /> <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.tablesorter.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.tablesorter.pager.js")" type="text/javascript"></script> 2. jQuery Sorting and Pagination script <script type="text/javascript"> $(function () { $("table.tablesorter").tablesorter({ widthFixed: true, sortList: [[0, 0]] }) .tablesorterPager({ container: $("#pager"), size: $(".pagesize option:selected").val() }); }); </script> So, with only two lines of code, I’m using both tablesorter and tablesorterPager plugins, giving some options to both these. Options added: tablesorter - widthFixed: true – gives fixed width of
the columns tablesorter - sortList[[0,0]] – An array of instructions for per-column sorting and direction in
the format: [[columnIndex, sortDirection], ... ] where columnIndex is a zero-based index for your columns left-to-right and sortDirection is 0 for Ascending and 1 for Descending. A valid argument that sorts ascending first by column 1 and then column 2 looks like: [[0,0],[1,0]] (source: http://tablesorter.com/docs/) tablesorterPager – container: $(“#pager”) – tells
the pager container,
the div with id pager in our case. tablesorterPager – size:
the default size of each page, where I get
the default value selected, so if you put selected to any other of
the options in your select list, you will have this number of rows as default per page for
the table too. END RESULTS 1. Table once
the page is loaded (default results per page is 5 and is automatically sorted by 1st column as sortList is specified) 2. Sorted by Phone Descending 3. Changed pagination to 10 items per page 4. Sorted by Phone and Name (use SHIFT to sort on multiple columns) 5. Sorted by Date Added 6. Page 3, 5 items per page ADDITIONAL ENHANCEMENTS We can do additional enhancements to
the table. We can make search for each column. I will cover this in one of my next blogs. Stay tuned. DEMO PROJECT You can download demo project source code from HERE.CONCLUSION Once you finish with
the demo, run your page and open
the source code. You will be amazed of
the purity of your code.Working with pagination in client side can be very useful. One of
the benefits is performance, but if you have thousands of rows in your tables, you will get opposite result when talking about performance. Hence, sometimes it is nice idea to make pagination on back-end. So,
the compromise between both approaches would be best to combine both of them. I use at most up to 500 rows on client-side and once
the user reach
the last page, we can trigger ajax postback which can get
the next 500 rows using server-side pagination of
the same data. I would like to recommend
the following blog post http://weblogs.asp.net/gunnarpeipman/archive/2010/09/14/returning-paged-results-from-repositories-using-pagedresult-lt-t-gt.aspx, which will help you understand how to return page results from repository. I hope this was helpful post for you. Wait for my next posts ;). Please do let me know your feedback. Best Regards, Hajan