ASP.NET MVC Grid

One of the questions when you start to build a web site is which grid should I use ? When deciding we should be focused on the following key grid features:

  • Lightweight
  • Bootstrap support
  • Localization
  • Customizable
  • Ajax support

Many open source and commercial solutions exists at the market but I prefer Grid.Mvc.

If you need Ajax support you have to install Grid.Mvc.Ajax which is available as NuGet package: NuGet Grid.Mvc.Ajax.
Note: If you install this package with NuGet it will automatically install Grid.Mvc.Redux which is enhancement to the Grid.Mvc.

This Ajax grid comes with Ladda support which gives you ability to merge loading indicators into the action that invoked them and is primarily intended for use with forms where it gives users immediate feedback upon submit. As I didn't need Ladda support because I have a global spinner for Ajax callbacks so I deleted all Ladda button references in javascript (gridmvc-ext.js ). I will give you an example what to delete:

Before:
var formButton = $("#" + self.gridFilterForm.attr('id') + "
                 input[type=submit],button[type=submit]")[0];
var l = Ladda.create(formButton);
l.start();
self.updateGrid(location.search, function () {
    l.stop();
});
After:
self.updateGrid(location.search, function () {});

And also don't forget to delete following code:

if (self.gridFilterForm) {
    var formButton = $("#" + self.gridFilterForm.attr('id') +                                                      "input[type=submit],button[type=submit]")[0];
    var l = Ladda.create(formButton);
    l.start();
}

I would suggest to look for "Ladda.create" and be careful to delete all references.

Another feature I customized was Ajax grid pager so that left button is always visible. I changed code in _AjaxGridPager.cshtml:

Before:
<li>
    <a href="#" class="grid-prev-page" 
    title="Previous Page" style="display:
    none">
        <span class="glyphicon glyphicon-step
        backward"></span>
    </a>
</li>
After:
<li>
    <a href="#" class="grid-prev-page"
    title="Previous Page" style="pointer
    events: none">
        <span class="glyphicon glyphicon-step
        backward"></span>
    </a>
</li>

To enable and disable clicks on left and right button left I changed gridmvc-ext.js file:

Before:
if (!response.HasItems) {
    nextPageLink.hide();
} else {
    nextPageLink.show();
}
if (self.currentPage == 1) {
    prevPageLink.hide();
} else {
    prevPageLink.show();
}
After:
if (!response.HasItems) {
    nextPageLink.css("pointer-events", "none");
} else {
    nextPageLink.removeAttr('style');
}
if (self.currentPage == 1) {
    prevPageLink.css("pointer-events", "none");
} else {
    prevPageLink.removeAttr('style');
}

Now when I have customized grid to fit my needs next challenge is how to properly use it because of poor documentation of Ajax extension. First I would recommend to read the documentation. The missing part in documentation are views.

In controller you have to create two actions as you can see in documentation. For example first action is Index and second is IndexGrid. In Index you will return the first page of query and in IndexGrid you will sort, paginate, filter or do whatever you want in query. IndexGrid is simply a partial view with table data. This partial view is rendered via Ajax callback. Here are examples of actions and views.

Index action
public ActionResult Index()
{
    var grid = (AjaxGrid<YourModel>)new
    AjaxGridFactory()
    .CreateAjaxGrid(IQueryable<YourModel>,
    1, false, 5);

    return View(grid);
}
IndexGrid action
[HttpGet]
public ActionResult IndexGrid(int? page)//you can get data from filter here
{
    //you can apply filters for your data here
    var grid =new                     AjaxGridFactory().CreateAjaxGrid(IQueryable<YourModel>, page.HasValue ? page.Value : 1, page.HasValue, 5);
    return Json(new { Html=
    grid.ToJson("_IndexGrid", this), grid.HasItems 
    }, JsonRequestBehavior.AllowGet);
}
Index view
@model Grid.Mvc.Ajax.GridExtensions.AjaxGrid<YourModel>

<div id="gridFilters">
    <input type="text" name="date">//if you want to send "date" to action
    <input type="text" name="search">
    ...
</div>

@{//to render grid
    Html.RenderPartial("_PackageGrid", Model);
 }

 @section scripts
 {//calling partial view for grid data
 <script type="text/javascript">
     $(document).ready(function () {
        var ajaxUrl = '/Controller/IndexGrid';
            pageGrids.nameGrid.ajaxify({
                getPagedData: ajaxUrl,
                getData: ajaxUrl,
                gridFilterForm: $("#gridFilters")
            });
        pageGrids.nameGrid.refreshFullGrid();
    });
 </script>
 }
IndexGrid partial view
@model Grid.Mvc.Ajax.GridExtensions.AjaxGrid<YourModel>

@Html.Grid(Model).Named("nameGrid").Columns(c =>
{
    c.Add(x => x.Id);
    ...
    //your columns here
}).WithPaging(5, 10)

If you use this Ajax grid library you can still use Grid.Mvc library with postbacks. It is not necessary to convert all of your grids to Ajax grid because it is only extension. The Grid.Mvc documentation is better than Grid.Mvc.Ajax documentation so all you have to do is follow instructions.

At the end...

Grid.Mvc with Grid.Mvc.Ajax extension is lighweight and open source so you can change it to fit your needs as I did with filters and pager. Maybe the documentation of Ajax extension could be better but at the end it was good choice.

Pros:

  • Open source
  • NuGet support: NuGet Grid.Mvc
  • Boostrap support
  • Sortable
  • Filterable
  • Customizable: source is availible, grid table and grid pager is availible as partial view

Cons:

  • Documentation could be better
  • Date filter problems if you have DateTime field but you want to filter by Date