Sunday, November 6, 2011

MVCfied Datatable.js

In my last post I discussed how to create a very simple MVC control which demonstrated a notion of ways things are done in MVC in contrast to web form.

This post will focus on explaining a real and sophisticated MVC control which encapsulates jquery.datatable.js and jquery.ui.sortable.js jquery plugins.

Jquery.datatables.js is one of the sophisticated jquery plugin which provides a way to build a grid with complex functionality such as paging, sorting, filtering and many more. And it is really easy to integrate with MVC. Before going through this article I suggest you to understand the capability of jquery.datatable plugin and how to work with it without encapsulating it into MVC control.



Please also take a look at sortable for sortable plugin which is useful for row sorting.

We won’t be going into details how these plugins work. Rather we will be focusing on how to encapsulate these jquery plugins in MVC and simplify the process of creating a reusable and interactive control which can do all the heavy lifting and return a sophisticated grid with just single line of code.

As you must have understood by now that MVC controls simply emits necessary html string which will be rendered to the browser. Unlike webform’s controls which participates in full page lifecycle, MVC control simply can be a class which returns full html string in it’s ToString() function including the necessary html element and javascripts. Whatever is returned is appended to the response stream. So you just need to make sure that you emit required html string and javascript properly and in correct order.

Let’s first create another jquery plugin wrapping around the existing datatable plugin. The purpose of this is to incorporate all the necessary boilerplate code before hand which will significantly reduce the amount of html code to be returned for each grid in your page. Remember it is not absolutely necessary, however you will come to realize its significance as you will start building one yourself. I’ve named it dataTableMVC.

Let’s flrst take a quick look at how the wrapper javascript plugin looks like. Open DataTableJS.js file under MVCExtended Project in Controls/contents/scripts folder.

I know the code is a lot. But as I told you this wrapper does all the heavy lifting works, simplifying the process of control development. You’ll be amazed to see how your control user will respond when they are able to create a full functional grid control in just a single line of code. The javascript function callRowSorted is a bit of extra work for sending the data back to the server after the rows have been sorted. It actually recreates a model and forms an array in the order they currently appear, to be returned to the server.

Now Let’s look at DataTableJS class

public class DataTableJS : MvcHtmlString

        public DataTableJS(string name, string url):base("")
            Name = name;
            Url = url;

public override string ToString()
            StringBuilder builder = new StringBuilder();
            //start building all the required html and javascript.

            return builder.ToString();

The class is really simple as I told you. It derives from MvcHtmlString, which is absolutely not necessary. You can just override the ToString() method from object and return all the required scripts and html tags in correct order.

All others are the properties and methods exposed to the control user if they want to tweak the default behaviours. There are some method chaining functions such as ApplySetting which takes a lambda expression as Action delegate. This delegate will be called at the end of the process while building the necessary html strings. The control user can provide a lambda expression which changes the default settings of the DataTableJS class.

DatatableJS control works with the viewmodel class. Your properties in viewmodel are decorated with the appropriate DataTableJSColumn attribute. The DataTableJSColumns are another powerful part of this control which is responsible to return the content in appropriate format and supply the necessary script blocks. Each type of Column is supplemented by its corresponding attribute type. The attributes simply encapsulates all the properties required by the corresponding column type which can be modified at attribute level. Attributes also facilitates this control to transform the viewmodel data into appropriate format to be returned to datatable.js plugin incase of serverside paging and sorting.

The viewmodel will look something like this.

public class PersonalInformation
        [DataTableJSColumn(ColumnIndex = 0,Title = "Sort Index")]
        public int SortIndex { get; set; }

        [DataTableJSLinkColumn("PersonId",BaseUrl = "localhost/personalinfo/",Title = "Select",CellText = "Retrieve",IsSortable = false,ColumnIndex = 0)]
        public int PersonId { get; set; }

        [DataTableJSCheckBoxColumn("PersonName", Title = "Select All", ColumnIndex = 1)]
        public string PersonName { get; set; }

        [DataTableJSColumnAttribute("EmailAddress", Title = "Email Address", ColumnIndex = 3)]
        public string EmailAddress { get; set; }

        [DataTableJSColumnAttribute("DateOfBirth", Title = "Date of Birth", FormatString = "MM/dd/yyyy", ColumnIndex = 2)]
        public DateTime DateOfBirth { get; set; }

        [DataTableJSColumn("Gender", Title = "Gender", ColumnIndex = 4)]
        public string Gender { get; set; }


You can use the control using the html extension as

<%= Html.DataTableJS("ss", Url.Action("GetData")).AutoGenerateColumns(true).ApplySetting((m) => { m.DisplayLength = 5; m.AutoWidth = false; m.IsServerSide = true; m.ColumnByName = false;
}).DefaultSortBy("SortIndex", "asc") %>

Please download and go through the code. And always remember that there are thousands of ways of doing things, and this is one among them. I don’t claim it to be the best way out there. So google a bit more and find out other best ways of doing so. If you have or find any link then please let me know so that I can learn it myself too.

There is a tiny bug related to row sorting while resending the data back to the server for persisting. Please ignore it for now.

Thank you all for reading the post.