Another early look at jQuery UI Grid in ASP.NET MVC – Data Types, Dataview, Pager, Sorting and Filtering

More than a year ago I took my first early look at jQuery UI Grid. Since that time a lot has changed in the plugin (and a lot will as the roadmap is placing Grid in 2.1 version of jQuery UI), so I've decided to take another early look at it.

This blog post talks about jQuery UI Grid plugin in Stage 3 of development, which is a pre-release version. Specific technical details may change before the final release of this product.

This is a minimal set of CSS and JavaScript files required by the plugin:
<script src="@Url.Content("~/Scripts/jquery-1.7.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.tmpl.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/ui/jquery.ui.core.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/ui/jquery.ui.widget.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/ui/jquery.ui.observable.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/ui/jquery.ui.dataview.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/ui/jquery.ui.grid.js")" type="text/javascript"></script>
You can find Grid specific files in its branch at GitHub (there is also a branch which is using JsRender instead of jQuery Templates).
The Grid is design to be used on table element. By default it will use the th elements text and data-* attributes for setting its columns and rowTemplate options. Thanks to that following markup is all what we need:
<table id="products">
  <thead>
    <tr>
      <th data-property="Id" data-type="number">Id</th>
      <th data-property="Name" data-type="string">Name</th>
      <th data-property="Supplier.Name" data-type="string">Supplier</th>
      <th data-property="Category.Name" data-type="string">Category</th>
      <th data-property="QuantityPerUnit" data-type="string">Quantity Per Unit</th>
      <th data-property="UnitPrice" data-type="number">Unit Price</th>
      <th data-property="UnitsInStock" data-type="number">Units In Stock</th>
    </tr>
  </thead>
  <tbody>
  </tbody>
</table>
If the default behaviour doesn't give the desired effect, developer can provide values for columns and rowTemplate himself. The rowTemplate option should be set to jQuery Templates template and the columns option should be set to an array of objects.
Currently planned low-level abstraction for retrieving data in jQuery UI project is Dataview, there are also three reusable extensions than we can play with: localDataview, odataDataview, preloaderDataview. In my sample projects I'm already using LINQ Dynamic Query Library so I thought it would be nice to have Dataview which would generate sorting and filtering expressions in a way I need them. General structure of Dataview extension looks like this:
(function($, undefined) {
  $.widget('ui.linqDataview', $.ui.dataview, {
    widgetEventPrefix: 'dataview',
      options: {
        //Here you can provide any additional options you want
        ...
        //This function will be called by Dataview to retrieve data
        source: function (request, response) {
          //'request' contains informations for data scope:
          //- request.paging.offset
          //- request.paging.limit
          //- request.sort.length
          //- request.filter (with request.filter[property].operator and request.filter[property].value)
          ...
          //when you fetch the data the 'response' function should be called
          //with actual data as first parameter and total rows count as second
        }
      }
  });
}(jQuery));
You can find the implementation for my usage of LINQ Dynamic Query Library purposes here. Thanks to this the action method for serving data can be as simple as this:
public ActionResult Products(int skip, int take, string orderby, string filter)
{
  var products = null;  
  if (!String.IsNullOrWhiteSpace(filter))
    products = _northwindContext.Products.Where(filter);
  else
    products = _northwindContext.Products;
  
  return Json(new
  {
    rows = products.Include(p => p.Category).Include(p => p.Supplier).OrderBy(orderby).Skip(skip).Take(take),
    count = products.Count()
  }, JsonRequestBehavior.AllowGet);
}
The LINQ Dynamic Query Library will do the rest.
On the client side I just need to reference the script file with the Dataview extension and initialize the widgets:
...
<script src="@Url.Content("~/Scripts/grid-spf/dataview-linq.js")" type="text/javascript"></script>
...
<script type="text/javascript">
  $(document).ready(function () {
    //Create Dataview based on the extension
    var products = $.ui.linqDataview({
      //Default sorting
      sort: ['Id'],
      //Action URL
      resource: '@Url.Action("Products")'
    });

    //Initialize the grid
    $('#products').grid({
      source: products
    });

    //Load from Dataview
    products.refresh();
  });
</script>
To make full use of Dataview capabilities we should add pager, sorting and filtering. We can find basic implementation for those features in grid-spf folder at GitHub. Before using those a placeholder for the pager needs to be added to the table element:
<table id="products">
  ...
  <tfoot>
    <tr>
      <td colspan="7">
        <span id="pager"></span>
      </td>
    </tr>
  </tfoot>
</table>
Now it's time to add remaining references and extend the initialization code:
...
<script src="@Url.Content("~/Scripts/ui/jquery.ui.button.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/grid-spf/pager.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/grid-spf/grid-sort.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/grid-spf/grid-filter.js")" type="text/javascript"></script>
...
<script type="text/javascript">
  $(document).ready(function () {
    ...

    //Initialize the grid
    $('#products').grid({
      source: products
    })
    //Enable sorting
    .gridSort()
    //Enable filtering
    .gridFilter();

    //Initialize pager
    $("#pager").pager({
      source: products
    });

    //Load from Dataview
    products.refresh();
  });
</script>
Everything is up and running now. The complete project is available in my svn repository at CodePlex.

8 comments:

Noob said...

Thanks for publishing all these useful articles. I am a complete noob using codeplex for accessing source repositories - can you give some pointers how I can download the source tree to my computer? E.g. the one at https://tpeczek.svn.codeplex.com/svn/trunk/MVC/jQuery%20UI%20Grid%20Examples/

Thanks again!

Tomasz Pęczek said...

This is standard SVN repository so you can use any SVN client you want, for example this --> http://tortoisesvn.tigris.org/

Noob said...

Yay! Now it worked. Initially, I wasn't using the https for some tries and combined with our extremely slow net-filter at work, I was kinda stuck. Putting in the https along with using the newest tortoise client from a fast box at home did the trick. Thanks!!

Anonymous said...

Hi,
I am getting the following error when i try to load jQuery UI Grid Example Soln.. Please help???
error : The project file 'E:\Asp.Net\MVC\MVCGrid\all\trunk\MVC\jQuery UI Grid Examples\jQuery.UI.Grid.jqGridDataview\jQuery.UI.Grid.jqGridDataview.csproj' cannot be opened.

The project type is not supported by this installation.

Tomasz Pęczek said...

Most probably you don't have NuGet installed (this project is using NuGet package restore).

Anonymous said...

just dropping by to say hey

Anonymous said...

Simply wish to say your article is as amazing.
The clearness in your post is just great
and i could assume you are an expert on this subject.

Well with your permission allow me to grab your feed
to keep updated with forthcoming post. Thanks a
million and please carry on the enjoyable work.


my page: krankenversicherung für referendare

Anonymous said...

Hey There. I found your blog using msn. This is a very well written
article. I will make sure to bookmark it and
return to read more of your useful info. Thanks for the post.

I'll definitely return.

Feel free to visit my web blog - Günstig Reisen Türkei