jQGrid and MVC 3 with Custom Paging and Custom Search Filters

During past some days I was studying MVC 3. In start I found MVC little bit challenging. But its features are really exiting, I believe MVC has the power of ASP .Net along with the flexibility of classic ASP.

While implementing data driven application in MVC you have three major choices for grids i.e. MVC DataGrid, jQGrid and MvcContrib grid. jQGrid is really something which has worked best for me. So, I am sharing a sample with you to highlight key features of jQGrid along with MVC.

First of all you have to download jQGrid from jQGrid Home Page. Also you can download the source code for this article.

Client Side Code

First you have to place some container divs where your grid will be rendered like this:-
<div id="content-grid">
    <table id="jq-grid" class="scroll" cellpadding="0" cellspacing="0">
    table>
    <div id="jq-grid-pager" class="scroll" style="text-aligncenter;">
    <div>
<div>
In jq-grid table, your grid will be rendered, while jq-grid-pager will be used for the pager in the grid.

Now you need to initate jQGrid with call to$("#jq-grid").jqGrid({ in your document.ready event. Here I am giving you a description of individual parameters which I used in my sample.

Url is used to point to the location from where grid will fetch the data.
url: 'http://localhost:60760/Home/GetList',//Service URL to fetch data

I generally uses JSON because it is really light weight
datatype: 'json',//Data Type which service will return

Now because I am using custom filters to search the records for my grid. So we have to explicitly pass them to server. They will be passed as JSON string in filters parameter or our server side function which I will discuss later.
postData://Data that will be posted with every request
{
filters: function () {
      return $.toJSON([
                          //Here add the parameters which you like to pass to server
                          { Key: "EmployeeName", Value: $("#txtEmployeeName").val() },
                          { Key: "Id", Value: $("#txtId").val() }
                    ]);
                     }
}

Now we define column and their properties through above code. I always like to fix the widths of columns, however you can ignore width parameter as well. Also note that in last column I disabled sorting using sortable:false.
colNames: ['Employee Id''Employee Name''Action'],//Column Names
colModel: [//Column details
           { name: "Employee Id", index: "Employee Id", width: "220px" },
           { name: "Employee Name", index: "Employee Name", width: "220px" },
           //Do not allow sorting on Action Column
           { name: "Action", index: "Action", sortable: false, width: "220px" }
          ],
I am persisting sort order, sort column, total pages and current page in session, so whenever page is reloaded, I am populating them  from my ViewBag.
sortname: '@ViewBag.EmployeeGridRequest.sidx',//This will persist sorting column 
sortorder: '@ViewBag.EmployeeGridRequest.sord'// This will persist sorting order 
rowNum: @ViewBag.EmployeeGridRequest.rows, //Total Pages
page: @ViewBag.EmployeeGridRequest.page, // Current Page
rowList: [@ViewBag.EmployeeGridRequest.rowList], // Page Selection Options

This one is simple, it will set the grid's caption, if you leave this blank then grid's header will be hidden.
caption: 'Employee Grid List',//Grid's Caption, you can set it to blank if you do not want this

Also there are some parameters which you should know, see above inline comments for their details.
altRows: true,//Use alternate row colors
altclass: 'jqgaltrow',//Alternate row class
hoverrows: true//Do not hover rows on mouse over
pager: $('#jq-grid-pager'),//Div in which pager will be displayed
toppager: true,
pgbuttons: true,//Show next/previous buttons
loadtext:'Loading Data please wait ...',
loadui :'block',//enable by default, block will disable inputs, remove this line if you do not want to block UI

I have created a function to load the data for grid whenever search or refresh button is pressed. Here is the code:-
    function reloadGrid(refresh) {
        if (refresh == true) {
            //Set initial values of your filters here
            $("#txtId").val("");
            $("#txtEmployeeName").val("");
    
            //reload grid's page 1 instead of current page
            $("#jq-grid").trigger("reloadGrid", { page: 1 });
        }
        else {
            $("#jq-grid").trigger("reloadGrid");
        }
    }
When I want to refresh grid, I set page:1, which will load the first page when ever you press refresh button.

Server Side Code
First Method which be called when Page is loaded is:-
[HttpGet]
public ActionResult Index()
{
    ViewBag.Filters = string.Empty;
    if (EmployeeGridRequest.DataFilters().Count > 0)
    {
        ViewBag.Filters = "$('#txtEmployeeName').val('" + EmployeeGridRequest.DataFilters()["EmployeeName"] + "');";
        ViewBag.Filters += "$('#txtId').val('" + EmployeeGridRequest.DataFilters()["Id"] + "');";
    }
 
    ViewBag.EmployeeGridRequest = EmployeeGridRequest;
    return View();
}
In above code I have checked from my session wrapper EmployeeGridRequest that if there is any filters available then use them to populate the initial values for the my filters and save in my ViewBag Object. As you can see below, in document.ready I have checked that if ViewBag contains filters then render them as Raw Html:-
$(document).ready(function () {
@if (ViewBag.Filters != string.Empty)
{
    @Html.Raw(ViewBag.Filters);
}

Now comes my main method which is responsible for providing data to grid. I have created some custom classes which encapsulate all the parameters which are used by jQGrid. So every time my implementation remains the same. See:-
[HttpGet]
        public JsonResult GetList(GridDataRequest request)
        {
            EmployeeGridRequest = request;
            var response = model.GetRecords(request);//Tricky Part Here :)
            var jsonData = new
            {
                total = response.TotalPages,
                page = request.page,
                records = response.TotalRecords,
                rows = response.Rows
            };
            return Json(jsonData, JsonRequestBehavior.AllowGet);
        }

Now in our model we have to create the list which we want to display in grid based on the parameters provided.
public GridDataResponse GetRecords(GridDataRequest request)
{
    .....
 GridDataResponse response = new GridDataResponse();
 response.TotalRecords = selectedList.Count;
 response.TotalPages = (int)Math.Ceiling((float)selectedList.Count() / (float)request.rows);
 response.Rows =
  (
  from item in selectedListAfterPagging
  select new GridDataDetail()
  {
   id = item.Id,
   cell = new string[] { 
   item.Id.ToString(),
   item.Name,
   "+item.Id.ToString()+"' title='Edit'>Edit " +
   "+item.Id.ToString()+"' title='Delete'>Delete"
   }
  }
  ).ToArray();
 return response;
}

I have used a List to store my Employee objects, this is only because I do not want to add a database to my sample, in real world off course you will be using database to access data. In above method I am creating a GridResponse object which will be bind with grid.
Since I am using custom paging instead of sending all records to client, so I have to manually calculate the no of records as i did:-
response.TotalPages = (int)Math.Ceiling((float)selectedList.Count() / (float)request.rows);

Also see that Grid detail object contain two properties i.e. id and cell. The id will be used as identified in grid and col will be bind to the columns in our grid.

Final Output

Take a look at our final output. First see how page is loaded first time:-
Now I have changed some sorting and applied filters to the grid.
Now edit some record by pressing edit link.
And press save button to get back to list page and see that our grid settings are persisted across page.

Finally its all done. And now you can see your grid in action. Hopefully this will be useful for you. Feel free to comment. Happy Coding !!!

Comments (33)

Loading... Logging you in...
  • Logged in as
The link to the download is not working
4 replies · active 562 weeks ago
This web page is not available
The web page at https://docs.google.com/open?id=0BwIncXQAuoQLeUs4... might be temporarily down or it may have moved permanently to a new web address.
2 replies · active 603 weeks ago
Very useful, thank you Zeeshan, I'was looking for this right solutions for get memory search state.

Bye
Sergio
1 reply · active 644 weeks ago
Abdul Latif's avatar

Abdul Latif · 644 weeks ago

Zeeshan, it is a very nice workout, thanks
1 reply · active 644 weeks ago
Nyc
1 reply · active 636 weeks ago
Kindly can anyone tell me how to open this project
with mvc 4 template
this arrticle is very helpfull.i work with database ver well..thanks..
1 reply · active 612 weeks ago
It is Working Fine ,but i m not getting how Edit Page is open after clicking Edit .where is the Code for that
1 reply · active 594 weeks ago
Hi Zeeshan,

I am able to make it work completely for asp.net mvc 2 project with the exception of persisting the paging. The only difference between your and mine implementation is I have used a separate popup box which will pop up on click of search icon in the toolbar. Can you please help me to know what I am missing. Need your help on this :)
1 reply · active 572 weeks ago
Thanks a lot for your article. It was very helpful to me :).
1 reply · active 571 weeks ago
Hi Zeeshan,

I am working with RAZOR view in MVC. I have created JQGrid to fetch the data and it's working fine.

I am new to JQGrid that's why I am facing difficulty to implement inline editing. Could you please help me in this?

Thanks in advance.

Srini
1 reply · active 571 weeks ago
This is very helpfull for me...Thanks Zeeshan
1 reply · active 523 weeks ago
but serverside paging working in this example
1 reply · active 473 weeks ago
Very nice and really smart working here in this site,Thanks admin for sharing this post,
1 reply · active 432 weeks ago
sadda

Post a new comment

Comments by