Desde que escribí mi primer post sobre como utilizar JqGrid con asp.net (http://geekswithblogs.net/jaullo/archive/2011/05/19/jqgrid-y-asp.net-un-primer-acercamiento.aspx) he recibido varias consultas sobre como realizar un maestro detalle utilizando este control de jquery.

Antes de comenzar debo mencionar que para mostrar un maestro detalle con JqGrid tenemos dos opciones:

1. Realizarlo con un subgrid

2. Utilizar dos JqGrid separados

Así que, teniendo esto en cuenta, el objetivo de este post será realizar el maestro detalle utilizando el Subgrid, que a mi parecer es mucho más agradable y por supuesto mas ordenado. Posteriormente en otro post veremos como hacerlo con 2 JqGrid separados.

Para este ejemplo, no voy a profundizar mucho en como esta formado JqGrid ni como llenar los datos, pues eso ya lo vimos en el anterior post y aplica exactamente de la misma forma para el grid padre como para el grid hijo, basicamente sería cambiar el nombre de la tabla y crea un nuevo stored procedure.

En lo que si nos vamos a enfocar es en como realizar la definición del subgrid.

Si recordamos un poco como esta conformado el JqGrid, veremos que al final de la definición del mismo este nos permite configurar las opciones adicionales que tendrá el control, como por ejemplo:

width: "850",
height: "100%

Es precisamente en esta serie de opciones donde tendremos que habilitar nuestro grid para que contenga un subgrid, esto lo hacemos agregando la opción:

subGrid: true

Luego de que hemos habilitado nuestro subgrid debemos crear la función subGridRowExpanded que será la encargada de mostrar nuestro subgrid cuando expandamos el grid padre, es precisamente dentro de esta función donde declararemos nuestro subgrid.

   1: subGridRowExpanded: function (subgrid_id, row_id) {
   2:                     // we pass two parameters 
   3:                     // subgrid_id is a id of the div tag created whitin a table data 
   4:                     // the id of this elemenet is a combination of the "sg_" + id of the row 
   5:                     // the row_id is the id of the row 
   6:                     // If we wan to pass additinal parameters to the url we can use 
   7:                     // a method getRowData(row_id) - which returns associative array in type name-value 
   8:                     // here we can easy construct the flowing 
   9:                     var subgrid_table_id, pager_id;
  10:                     subgrid_table_id = subgrid_id + "_t";
  11:                     pager_id = "p_" + subgrid_table_id;
  12:                     $("#" + subgrid_id).html("<table id='" + subgrid_table_id + "' class='scroll'></table><div id='" + pager_id + "' class='scroll'></div>");
  13:  
  14:                     jQuery("#" + subgrid_table_id).jqGrid({
  15:                         //este es mi subgrid
  16:  
  17:                         datatype: function () {
  18:                             $.ajax(
  19:                 {
  20:                     url: "webservices/LoadChild.asmx/GetChilds", //PageMethod
  21:                     data: "{'pPageSize':'" + $("#" + subgrid_table_id).getGridParam("rowNum") +
  22:                     "','pCurrentPage':'" + $("#" + subgrid_table_id).getGridParam("page") +
  23:                     "','pSortColumn':'" + $("#" + subgrid_table_id).getGridParam("sortname") +
  24:                      "','id':'" + $("#" + subgrid_table_id).getGridParam("ajaxGridOptions") +
  25:                     "','pSortOrder':'" + $("#" + subgrid_table_id).getGridParam("sortorder") + "'}", //PageMethod Parametros de entrada
  26:  
  27:                     dataType: "json",
  28:                     type: "post",
  29:                     contentType: "application/json; charset=utf-8",
  30:                     complete: function (jsondata, stat) {
  31:                         if (stat == "success")
  32:                             jQuery("#" + subgrid_table_id)[0].addJSONData(JSON.parse(jsondata.responseText).d);
  33:                         else
  34:                             alert(JSON.parse(jsondata.responseText).Message);
  35:                     }
  36:                 });
  37:                         },
  38:                         jsonReader: //Set the jsonReader to the JQGridJSonResponse squema to bind the data.
  39:             {
  40:             root: "Items",
  41:             page: "CurrentPage",
  42:             total: "PageCount",
  43:             records: "RecordCount",
  44:             repeatitems: true,
  45:             cell: "Row",
  46:             id: "ID" //index of the column with the PK in it    
  47:         },
  48:  
  49:                         colModel:
  50:                 [
  51:                   { name: 'ChildId', index: 'ChildId', width: 40, align: 'left', editable: false, editrules: { edithidden: true }, hidden: true },
  52:                   { name: 'ChildName', index: 'ChildName', width: 80, align: 'left', editable: true, edittype: 'text' },
  53:                   { name: 'ChildLastName', index: 'ChildLastName', width: 200, align: 'left', editable: true, edittype: 'text', editoptions: { size: 20, maxlength: 30} },
  54:                   { name: 'ChildBirthDate', index: 'ChildBirthDate', width: 300, align: 'left', editable: true, edittype: 'select', editoptions: { size: 20, maxlength: 30} },
  55:                   { name: 'PersonId', index: 'PersonId', width: 200, align: 'left', editable: true, edittype: 'text', editoptions: { size: 20, maxlength: 30 }, formater: 'number'}],
  56:  
  57:                         pager: pager_id, //Pager.
  58:                         loadtext: 'Cargando datos...',
  59:                         recordtext: "{0} - {1} de {2} elementos",
  60:                         emptyrecords: 'No hay resultados',
  61:                         pgtext: 'Pág: {0} de {1}', //Paging input control text format.
  62:                         rowNum: "10", // PageSize.
  63:                         ajaxGridOptions: row_id,
  64:                         rowList: [10, 20, 30], //Variable PageSize DropDownList. 
  65:                         viewrecords: true, //Show the RecordCount in the pager.
  66:                         multiselect: false,
  67:                         sortname: "ChildName", //Default SortColumn
  68:                         sortorder: "asc", //Default SortOrder.
  69:                         width: "800",
  70:                         height: "100%",
  71:                         caption: "Invoice Detail"
  72:                     });
  73:                     jQuery("#" + subgrid_table_id).jqGrid('navGrid', "#" + pager_id, { edit: false, add: false, del: false })
  74:                 },

Si vemos el código anterior, la definición del subgrid es exactamente igual a como hemos realizado la definición del grid padre, solo que dentro de una función contenedora.

Finalmente, así se vería

Por último el código de ejemplo

Gracias a los comentarios de muchos, actualizo el post para agregar el Stored Procedure GetChilds, que lo disfruten

   1: USE [JQGrid]
   2: GO
   3: /****** Object:  StoredProcedure [dbo].[GetChilds]    Script Date: 07/27/2012 17:55:56 ******/
   4: SET ANSI_NULLS ON
   5: GO
   6: SET QUOTED_IDENTIFIER ON
   7: GO
   8:  
   9: -- GetPersons 3, 4, 'LastName', 'desc'
  10:  
  11: ALTER procedure [dbo].[GetChilds]
  12:  
  13: @PageSize int , 
  14: @CurrentPage int , 
  15: @SortColumn varchar(20), 
  16: @SortOrder varchar(4),
  17: @PersoId int
  18:  
  19: as
  20:  
  21: declare @RecordCount int
  22: declare @PageCount int
  23: declare @PageIndex int
  24:  
  25: Select @RecordCount = count(ChildId)
  26: from Childs
  27:  
  28: set @PageCount = Ceiling(cast (@RecordCount as float) / cast (@PageSize as float))
  29:  
  30: if (@CurrentPage > @PageCount) set @CurrentPage = @PageCount
  31:  
  32: set @PageIndex = @CurrentPage - 1
  33:  
  34: Select RecordCount = @RecordCount, PageCount = @PageCount, CurrentPage = @CurrentPage
  35:  
  36: declare @Query varchar(300)
  37:  
  38: set @Query = 
  39:     'Select ChildId, ChildName, ChildLastName, ChildBirthDate,PersonId, 
  40:      RowNumber = ROW_NUMBER() OVER (ORDER BY ' + @SortColumn + ' ' + @SortOrder + ')
  41:      from Childs' 
  42:  
  43: set @Query = 
  44:     'Select ChildId, ChildName, ChildLastName, ChildBirthDate,PersonId
  45:      from (' + @Query + ' )as result 
  46:      where PersonId='+ CAST(@PersoId as varchar(5)) +' and RowNumber BETWEEN ' + cast(@PageSize * @PageIndex + 1 as varchar(10)) + ' 
  47:                     AND ' + cast(@PageSize * (@PageIndex + 1) as varchar(10)) 
  48:                     
  49:  
  50:  
  51: Exec (@Query)