jqGrid and ASP.NET MVC - Subgrid

An easy subject this time. To configure subgrid we need to add few parameters to grid initialization code:
<script type="text/javascript">
  $(document).ready(function() {
    $('#jqgOrders').jqGrid({
      //url from wich data should be requested
      url: '/Home/OrdersGridData/',
      //type of data
      datatype: 'json',
      //url access method type
      mtype: 'GET',
      //columns names
      colNames: ['OrderID', 'Customer', 'Employee', 'OrderDate', 'RequiredDate', 'ShippedDate', 'ShipCountry'],
      //columns model
      colModel: [
                  { name: 'OrderID', index: 'OrderID', align: 'left' },
                  { name: 'Customer', index: 'CustomerID', align: 'left' },
                  { name: 'Employee', index: 'EmployeeID', align: 'left' },
                  { name: 'OrderDate', index: 'OrderDate', align: 'left' },
                  { name: 'RequiredDate', index: 'RequiredDate', align: 'left' },
                  { name: 'ShippedDate', index: 'ShippedDate', align: 'left' },
                  { name: 'ShipCountry', index: 'ShipCountry', align: 'left' }
                ],
      //pager for grid
      pager: $('#jqgpOrders'),
      //number of rows per page
      rowNum: 10,
      //initial sorting column
      sortname: 'OrderID',
      //initial sorting direction
      sortorder: 'asc',
      //we want to display total records count
      viewrecords: true,
      //grid width
      width: 'auto',
      //grid height
      height: 'auto',
      //enable subgrid
      subGrid: true,
      //subrid model
      subGridModel: [{
                       //subgrid columns names
                       name: ['ProductName', 'UnitPrice', 'Quantity', 'Discount'],
                       //subgrid columns widths
                       width: [200, 100, 100, 100],
                       //subrig columns aligns
                       align: ['left', 'left', 'left', 'left']
                     }],
      //url from which subgrid data should be requested
      subGridUrl: '/Home/OrdersDetailsSubgridData/'
    });
  });
</script>

Controller action for main grid is pretty standard (you can take a look at corresponding sample in jqGrid basics post). The one for subgrid is slightly different. That's because of  the different data format - subgrid takes only rows collection with cell table inside.
/// <summary>
///
Provides json data for jqGrid subgrid
/// </summary>
/// <param name="id">
parent row id</param>
/// <returns>json data</returns>
public ActionResult OrdersDetailsSubgridData(string id)
{
  //Preparing anonymous variable with json data
  var ordersDetails = new
  {
    rows = (from orderDetails in _repository.GetOrderDetails(Convert.ToInt32(id))
            select new
            {
              //table of cells values
              cell = new string[] {
                                    orderDetails.Product.ProductName,
                                    orderDetails.UnitPrice.ToString(),
                                    orderDetails.Quantity.ToString(),
                                    orderDetails.Discount.ToString()
                                  }
            }
           ).ToArray()
  };

  //Returning json data
  return Json(ordersDetails);
}

Subgrid is very limited (no support for paging, sorting, searching and editing). There is a solution which uses some of the subgrid functions of the main grid to create not a subgrid, but another fully functional grid. This solution is well described here and I'm not going to dig into it (it's just a little bit tricky initialization javascript). Let's take a look at standard subgrid we have created:

Of course you can download sample application here.

9 comments:

Air said...

Hi,

Excellent Work! I could not get the subgrid working.I debuged the app I see the method is called OrdersGridData(string sidx, string sord, int page, int rows) and the data is returned to the Subgrid.aspx, but the grid is empty no rows. The serach works just fine. Do you have any idea what's going on..?

Thanks,

Joe

Tomasz Pęczek said...

Hi,

The only situation I can think of, is when you are trying to run sample on ASP.NET MVC 2. In tat case sample might not work because of some security changes. If thats the case, change last line of OrdersGridData action to this:

return Json(ordersData, JsonRequestBehavior.AllowGet);

Anonymous said...

Thanks Tomasz,

Yes. I'm using VS2010 MVC 2.0

Tomasz Pęczek said...

So I assume that this little change have solved your problem? I will try to find some time soon and migrate the sample the ASP.NET MVC 2.

Anonymous said...

Hi Tomasz,

Everything’s working just fine.

Thanks again

HarryBhasin said...

Gr8 Work....Please tell how to download file, as it is not in zip file format..

Tomasz Pęczek said...

If you want to download from URL provided in post, you may use an SVN client (for example TortoiseSVN). There is also .zip download available here: http://tpeczek.codeplex.com/

Anonymous said...

How do you pass the value of the id when you call Orderdetails? I got the error: The parameters dictionary contains a null entry for parameter of non-nullable type 'System.Int32' for method:...

The only difference is that I have Orderdetails in another controller like

subGridUrl: '@Url.Action("OrderDetails")'

Tomasz Pęczek said...

This value is added internally by jqGrid. It takes the value which was provided as the row id (for the main grid rows) and adds it the the subgrid request as URL parameter "id".