2

I was trying to build a subgrid using jQGrid to show parent child relationship. I followed Manager and Employee relationships. I am building a JSON at server and this is how it looks

{"total":1,"page":1,"records":20,
"rows":[{"id":"Mgr 001","EmpId":"Mgr 001","Manager Name":"Murali","Dept":"D1"
 ,"Employees":[{"EmpId":"Emp 100","Name":"Alex","Dept":"Infrastucture"}]}]

The problem is when i click on expand i am finding the data from locally stored employeeLocalJSON variable and assigning the collection to subgrid. But it was not shown in subgrid. I have no idea why it is so. I want to load json from server and to show subgrid i should use the same, so i stored that one in local variable employeeLocalJSON.

I followed jqgrid subgrids from a single nested json

jqGrid Subgrid with "local" Data

JqGrid with subgrid and single XML file as input

Here is my jQGrid code

$(function() {

var employeeLocalJSON;
jQuery("#list").jqGrid({
    //start
    url: '/Employee/Search',
    datatype: "json",
    postData: {
        searchModel: function () {
            var result = {}, i, item,
             formInfo = $('#search-form').serializeArray(),
             l = formInfo.length;
            for (i = 0; i < l; i++) {
                item = formInfo[i];
                result[item.name] = item.value;
            }
            return JSON.stringify(result);
        }
    },
    mtype: "POST",
    colNames: ['id', 'EmpId', 'Manager Name', 'Dept'],
    colModel: [
    { name: 'id', index: 'id', hidden: true, width: 1, align: 'left', key: true },
    { name: 'EmpId', index: 'EmpId', search: true, width: 260, align: 'left' },
    { name: 'ManagerName', index: 'ManagerName', search: false, width: 110, align: 'left' },
    { name: 'Dept', index: 'Dept', search: true, width: 54, align: 'left' }],
    pager: $("#pager"),
    rowNum: 20,
    rowList: [5, 10, 20, 50],
    sortname: 'EmpId',
    sortorder: "asc",
    viewrecords: true,
    loadonce: true,
    sortable: true,
    jsonReader: {
        repeatitems: false
    },
    loadComplete: function (data) {
        if (data.rows) {
            employeeLocalJSON = data.rows; // save original JSON data
        }
    },
    caption: 'Employee Manager Detail',
    subGrid: true,
    subGridOptions: {
        "plusicon": "ui-icon-triangle-1-e",
        "minusicon": "ui-icon-triangle-1-s",
        "openicon": "ui-icon-arrowreturn-1-e",
        "reloadOnExpand": false,
        "selectOnExpand": true
    },
    subGridRowExpanded: function (grid_id, row_id) {
        //            //start of subgrid row expanded
        var subgrid_table_id, pager_id;
        subgrid_table_id = grid_id + "_tone";
        pager_id = "pone_" + subgrid_table_id;
        $("#" + grid_id).html("<table id='" + subgrid_table_id + "' class='scroll' style='width:100%'></table><div id='" + pager_id + "' class='scroll'></div>");
        var indexes = $(this).jqGrid('getGridParam', '_index');

        var empList = employeeLocalJSON[indexes[row_id]].Employees;

        $("#" + subgrid_table_id).jqGrid({
            datatype: 'local',
            data: empList,
            colNames: ['EmpId', 'Name', 'Dept'],
            colModel: [
                        { name: 'EmpId', width: 170 },
                        { name: 'Name', width: 110 },
                        { name: 'Dept', width: 60 }
                       ],
            sortname: 'EmpId',
            viewrecords: true,
            sortorder: "asc",
            width: 960
        });
    }

    //end
});
//                         });
jQuery("#list").jqGrid('navGrid', '#pager', { add: false, edit: false, del: false });
});

How do i achieve loading sub grid from a single JSON? What could be wrong in my code? I am not able to see the subgrid, even i bound a data

Community
  • 1
  • 1
Murali Murugesan
  • 22,423
  • 17
  • 73
  • 120

1 Answers1

2

The first important problem which you have is the usage of spaces in id values (see "id":"Mgr 001" in your data). I can suggest you two alternative to fix the problem. The first one will be to change the algorithm how you generate id values. For example you can just remove all spaces from the id if it is possible or replace " " to any other character. Another alternative will be to change the line of jqGrid code

return String(sid).replace(/[!"#$%&'()*+,.\/:;<=>?@\[\\\]\^`{|}~]/g,"\\$&");

to

return String(sid).replace(/[!"#$%&'()* +,.\/:;<=>?@\[\\\]\^`{|}~]/g,"\\$&");

(add space to the list of characters which should be encoded by jqGrid).

To post subgrid information in one response together with the main grid data I suggest you to use userdata part of JSON which will be accessed later as "userData" (case is important !!!) parameter of jqGrid. If you can't do this on the server side you can make the corresponding transformation of the server response inside of beforeProcessing callback. See the answer for the corresponding code example.

UPDATED: I reminded Tony one more time (see here) about the suggestion to escape spaces in the id. Just now (see here) the change is included in the main code of jqGrid. So in the next version (higher as the current 4.4.3) jqGrid will work with ids having spaces.

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • This works perfect! I found that jQuery("#" + subgrid_table_id) is empty because of the spaces in id. Though i use minified version of 4.4.1, i decided to remove spaces in server side code. It could be helpful if we do this ID space issue as a fix in original source. It just a thought, not sure about the impact/breaking existing code – Murali Murugesan Jan 28 '13 at 12:04
  • @Murali: You are welcome! I suggested Tony Tomov to include space in the list of escaped characters (see [here](http://www.trirand.com/blog/?page_id=393/bugs/usage-of-jgrid-jqid-everywhere-where-its-needed/#p26011)), but the fix is still not included in the code of jqGrid. Probably I should remind Tony one more time about the suggestion. In last 10 days you are the third person which had problems with subgrid and ids which contains spaces. By the way, I see that you'n found workaround for the problem with posting forma data to the controller. Isn't so? – Oleg Jan 28 '13 at 12:10
  • I am facing another problem with removing 'loadonce:true'. I removed this to do server side paging and sorting. But if i remove, this line var indexes = $(this).jqGrid('getGridParam', '_index'); in subGridRowExpanded function, it is not giving me a data. Any idea why is this happening? – Murali Murugesan Jan 28 '13 at 12:21
  • 1
    @Murali: The internal parameters `_index` and `data` will be filled by jqGrid only for local datatype of in case of usage `loadonce: true`. So you have to save your custom data (extensions to the standard JSON input of jqGrid) yourself in some place. For example I suggested you in my answer to use `userdata` for the case. Alternatively you can get the required data from `employeeLocalJSON` which you use currently. – Oleg Jan 28 '13 at 12:27
  • I used alternative way looping through employeeLocalJSON with row_id and got succeeded. Everything works fine. Thanks for spending your time though you have a busy schedule. – Murali Murugesan Jan 28 '13 at 12:38
  • @Murali: Looping is slowly as direct access to dictionary (to object with `id` property). If you have rowid you need to get the subgrid data which corresponds the row with the id. So it's better to create object having rowids as property name and the corresponding subgrid data as the value. Then you could just use something like `subgriddata[rowid]` to get the data for the row. `_index` is exactly the same and the structure which I built in `userdata` is also the same. – Oleg Jan 28 '13 at 13:12
  • Thanks Oleg. If i am correct i need to prepare this lookup in loadComplete: function (data) { //preparing dictionary obj }. Or is there other place i should? – Murali Murugesan Jan 28 '13 at 13:17
  • @Murali: If you would place the information *on the server part* in the `userdata` part of the responses then you don't need to do anything in more slowly client code. You will need just get the dictionary with `$(this).jqGrid("getGridParam", "userData")`. If you do prefer to create the dictionary on the client side then `loadComplete` or `beforeProcessing` are good placed for the job. – Oleg Jan 28 '13 at 13:26
  • @Murali: The main code of jqGrid on github is changed to support spaces in id. See **UPDATED** part of my answer. – Oleg Jan 29 '13 at 08:42
  • Thanks Oleg! Glad to see this fix in original source – Murali Murugesan Jan 29 '13 at 08:48