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