jqGrid : issue loading nested sub grid with local datatype
Asked Answered
P

1

5

I'm trying to get nested subgrids to work using jqGrid with local data. I've searched around quite a bit but haven't been able to find a solution. Here is a simplified sample of my code:

var mainGridData =
    [
        // main grid data
        { id: "m1", col1: "11", col2: "12" },
        { id: "m2", col1: "21", col2: "22" },
        { id: "m3", col1: "31", col2: "32" }
    ];
var firstSubgrid =
    {
        m1: [
            // data for subgrid for the id=m1
            { id: "s1a", c1: "aa", c2: "ab", c3: "ac" },
            { id: "s1b", c1: "ba", c2: "bb", c3: "bc" },
            { id: "s1c", c1: "ca", c2: "cb", c3: "cc" }
        ],
        m2: [
            // data for subgrid for the id=m2
            { id: "s2a", c1: "xx", c2: "xy", c3: "xz" }
        ]
    };
var secondSubgrid =
    {
        s1a: [
            // data for subgrid for the id=m1
            { id: "2s1a", d1: "2aa", d2: "2ab", d3: "2ac" },
            { id: "2s1b", d1: "2ba", d2: "2bb", d3: "2bc" },
            { id: "2s1c", d1: "2ca", d2: "2cb", d3: "2cc" }
        ],
        s2a: [
            // data for subgrid for the id=m2
            { id: "2s2a", d1: "xx", d2: "xy", d3: "xz" }
        ]
    };


//------------
$("#grid").jqGrid({
    datatype: 'local',
    data: mainGridData,
    colNames: ['Column 1', 'Column 2'],
    colModel: [
        { name: 'col1', width: 200 },
        { name: 'col2', width: 200 }
    ],
//Subgrid1...
    subGrid: true,
    subGridRowExpanded: function (subgridDivId, rowId) {
        var subgridTableId = subgridDivId + "_t";
        $("#" + subgridDivId).html("<table id='" + subgridTableId + "'></table>");
        $("#" + subgridTableId).jqGrid({
            datatype: 'local',
            data: firstSubgrid[rowId],
            colNames: ['Col 1', 'Col 2', 'Col 3'],
            colModel: [
                { name: 'c1', width: 100 },
                { name: 'c2', width: 100 },
                { name: 'c3', width: 100 }
            ],
      //Subgrid2...    
            subGrid: true,
            subGridRowExpanded: function (subgrid2DivId, subRowId2) {
                var subgrid2TableId = subgrid2DivId + "_t";
                $("#" + subgrid2DivId).html("<table id='" + subgrid2DivId + "'></table>");
                $("#" + subgrid2TableId).jqGrid({
                    datatype: 'local',
                    data: secondSubgrid[subRowId2],
                    colNames: ['Col 1', 'Col 2', 'Col 3'],
                    colModel: [
                        { name: 'd1', width: 100 },
                        { name: 'd2', width: 100 },
                        { name: 'd3', width: 100 }
                    ],
                });

            }                
        });
    }
});

Any ideas out there?

Pentose answered 7/12, 2012 at 16:48 Comment(0)
I
9

I find your question interesting. I think the answer could be helpful for many other people. So I wrote two demos where I demonstrate how the requirements could be implemented.

enter image description here

The first demo are base on the demo from my previous answer (which are based in another one) which code you use already used in the text of your question. I added the trick from the answer additionally to hide the subgrid icon ("+") for the rows which has no subgrids.

To simplify the holding of subgrid data I added in every row subgrid property which value are the data for the subgrid. The kind of holding the data is very practical because jqGrid save full items of the row so you don't need any hidden columns more. To access to the local data I recommend to use getLocalRow method. See the answer for example for additional information or the source code of getLocalRow method which is very simple.

The code of the first demo:

var myData = [
        // main grid data
        { id: "m1", col1: "11", col2: "12",
            subgrid: [
                // data for subgrid for the id=m1
                { id: "s1a", c1: "aa", c2: "ab", c3: "ac",
                    subgrid: [
                        // data for subgrid for the id=m1, subgridId=s1a
                        { id: "2s1a", d1: "2aa", d2: "2ab", d3: "2ac" },
                        { id: "2s1b", d1: "2ba", d2: "2bb", d3: "2bc" },
                        { id: "2s1c", d1: "2ca", d2: "2cb", d3: "2cc" }
                    ]},
                { id: "s1b", c1: "ba", c2: "bb", c3: "bc" },
                { id: "s1c", c1: "ca", c2: "cb", c3: "cc" }
            ]},
        { id: "m2", col1: "21", col2: "22",
            subgrid: [
                // data for subgrid for the id=m2
                { id: "s2a", c1: "xx", c2: "xy", c3: "xz",
                    subgrid: [
                        // data for subgrid for the id=m2, subgridId=s2a
                        { id: "2s2a", d1: "xx", d2: "xy", d3: "xz" }
                    ]}
            ]},
        { id: "m3", col1: "31", col2: "32" }
    ],
    removeSubgridIcon = function () {
        var $this = $(this);
        $this.find(">tbody>tr.jqgrow>td.ui-sgcollapsed").filter(function () {
            var rowData = $this.jqGrid("getLocalRow",
                    $(this).closest("tr.jqgrow").attr("id"));
            return rowData.subgrid == null;
        }).unbind("click").html("");
    },
    isHasSubrids = function (data) {
        var l = data.length, i;
        for (i = 0; i < l; i++) {
            if (data[i].subgrid != null) {
                return true;
            }
        }
        return false;
    };

$("#list").jqGrid({
    datatype: "local",
    data: myData,
    colNames: ["Column 1", "Column 2"],
    colModel: [
        { name: "col1", width: 200 },
        { name: "col2", width: 200 }
    ],
    gridview: true,
    rownumbers: true,
    autoencode: true,
    sortname: "col1",
    sortorder: "desc",
    height: "100%",
    pager: "#pager",
    caption: "Demonstrate how to create subgrid from local hierarchical data",
    subGrid: isHasSubrids(myData),
    loadComplete: function () {
        removeSubgridIcon.call(this);
    },
    subGridRowExpanded: function (subgridDivId1, rowId1) {
        var $subgrid1 = $("<table id='" + subgridDivId1 + "_t'></table>"),
            localRowData1 = $(this).jqGrid("getLocalRow", rowId1);
        $subgrid1.appendTo("#" + $.jgrid.jqID(subgridDivId1));
        $subgrid1.jqGrid({
            datatype: "local",
            data: localRowData1.subgrid,
            colNames: ["Colunm1", "Colunm2", "Colunm3"],
            colModel: [
                { name: "c1", width: 112 },
                { name: "c2", width: 112 },
                { name: "c3", width: 112 }
            ],
            gridview: true,
            rownumbers: true,
            autoencode: true,
            sortname: "c1",
            sortorder: "desc",
            height: "100%",
            loadComplete: removeSubgridIcon,
            subGrid: isHasSubrids(localRowData1.subgrid),
            subGridRowExpanded: function (subgridDivId2, rowId2) {
                var $subgrid2 = $("<table id='" + subgridDivId2 + "_t'></table>"),
                    localRowData2 = $(this).jqGrid("getLocalRow", rowId2);
                $subgrid2.appendTo("#" + $.jgrid.jqID(subgridDivId2));
                $subgrid2.jqGrid({
                    datatype: "local",
                    data: localRowData2.subgrid,
                    colNames: ["Col 1", "Col 2", "Col 3"],
                    colModel: [
                        { name: "d1", width: 90 },
                        { name: "d2", width: 90 },
                        { name: "d3", width: 90 }
                    ],
                    gridview: true,
                    rownumbers: true,
                    autoencode: true,
                    sortname: "d1",
                    sortorder: "desc",
                    height: "100%",
                    subGrid: isHasSubrids(localRowData2.subgrid),
                    loadComplete: removeSubgridIcon
                });
            }
        });
    }
});

The second demo is more deep modifications of the previous demo. It can be used in case of creating really deep multilevel subgrids. I used in the demo additionally intensive idPrefix to simplify working with ids. I recommend to compare values of id properties of items of myData array in the first demo and in the second one. The code of the second demo is below

var myData = [
        // main grid data
        { id: "1", col1: "11", col2: "12",
            subgrid: [
                // data for subgrid for the id=m1
                { id: "1", c1: "aa", c2: "ab", c3: "ac",
                    subgrid: [
                        // data for subgrid for the id=m1, subgridId=s1a
                        { id: "1", d1: "2aa", d2: "2ab", d3: "2ac" },
                        { id: "2", d1: "2ba", d2: "2bb", d3: "2bc" },
                        { id: "3", d1: "2ca", d2: "2cb", d3: "2cc" }
                    ]},
                { id: "2", c1: "ba", c2: "bb", c3: "bc" },
                { id: "3", c1: "ca", c2: "cb", c3: "cc" }
            ]},
        { id: "2", col1: "21", col2: "22",
            subgrid: [
                // data for subgrid for the id=m2
                { id: "1", c1: "1xx", c2: "1xy", c3: "1xz",
                    subgrid: [
                        // data for subgrid for the id=m2, subgridId=s2a
                        { id: "1", d1: "2xx", d2: "2xy", d3: "2xz" }
                    ]}
            ]},
        { id: "3", col1: "31", col2: "32" }
    ],
    removeSubgridIcon = function () {
        var $this = $(this),
            idPrefix = $this.jqGrid("getGridParam", "idPrefix");
        $this.find(">tbody>tr.jqgrow>td.ui-sgcollapsed").filter(function () {
            var rowData = $this.jqGrid("getLocalRow",
                    $.jgrid.stripPref(idPrefix, $(this).closest("tr.jqgrow").attr("id")));
            return rowData.subgrid == null;
        }).unbind("click").html("");
    },
    isHasSubrids = function (data) {
        var l = data.length, i;
        for (i = 0; i < l; i++) {
            if (data[i].subgrid != null) {
                return true;
            }
        }
        return false;
    },
    specificGridOptions = [
        {
            colNames: ["Column 1", "Column 2"],
            colModel: [
                { name: "col1" },
                { name: "col2" }
            ],
            cmTemplate: { width: 200 },
            sortname: "col1",
            sortorder: "desc",
            idPrefix: "s_",
            pager: "#pager",
            caption: "Demonstrate how to create subgrid from local hierarchical data"
        },
        {
            colNames: ["Colunm1", "Colunm2", "Colunm3"],
            colModel: [
                { name: "c1" },
                { name: "c2" },
                { name: "c3" }
            ],
            cmTemplate: { width: 112 },
            sortname: "c1",
            sortorder: "desc"
        },
        {
            colNames: ["Col 1", "Col 2", "Col 3"],
            colModel: [
                { name: "d1" },
                { name: "d2" },
                { name: "d3" }
            ],
            cmTemplate: { width: 90 },
            sortname: "d1",
            sortorder: "desc"
        }
    ],
    commonGridOptions = {
        datatype: "local",
        gridview: true,
        rownumbers: true,
        autoencode: true,
        height: "100%",
        loadComplete: function () {
            // one can use loadComplete: removeSubgridIcon, but I included
            // curent implementation of loadComplete only to show how to call
            // removeSubgridIcon from your loadComplete callback handler
            removeSubgridIcon.call(this);
        },
        subGridRowExpanded: function (subgridDivId, rowId) {
            var $subgrid = $("<table id='" + subgridDivId + "_t'></table>"),
                subgridLevel = $(this).jqGrid("getGridParam", "subgridLevel") + 1,
                parentIdPrefix = $(this).jqGrid("getGridParam", "idPrefix"),
                pureRowId = $.jgrid.stripPref(parentIdPrefix, rowId),
                localRowData = $(this).jqGrid("getLocalRow", pureRowId);
            $subgrid.appendTo("#" + $.jgrid.jqID(subgridDivId));
            $subgrid.jqGrid($.extend(true, {}, commonGridOptions, specificGridOptions[subgridLevel], {
                data: localRowData.subgrid,
                subGrid: isHasSubrids(localRowData.subgrid),
                subgridLevel: subgridLevel,
                idPrefix: rowId + "_",
                rowNum: 10000 // we use this to have no pager in the subgrids
            }));
        }
    };

$("#list").jqGrid($.extend(true, {}, commonGridOptions, specificGridOptions[0], {
    data: myData,
    subgridLevel: 0,
    subGrid: isHasSubrids(myData)
}));
Irreverence answered 8/12, 2012 at 16:52 Comment(6)
Thanks Oleg, great solution! I was starting to lose hope until seeing this. This is just what I'm looking for. Keep up the good work. (I tried to up vote as the answer but I don't have enough reputation points..)Pentose
@neverwinter: it's depend on which editing mode you want to use and where to save the modifications. In case of local editing in cell editing mode you need just add cellEdit: true, cellsubmit: "clientArray" options to all grids/subgrids which need be editable.Irreverence
@Irreverence my data was in [{id:1,code:"112",name:"aa","group":"1"},{id:2,code:"112",name:"aa","group":"2"},{id:3,code:"113",name:"bb","group":"1"},{id:4,code:"113",name:"bb","group":"2"}] and i converted this into this format data["112"] = {code:"112",name:"aa",subgrid[{grp1obj,grp2obj}]}, data["113"] = {code:"113",name:"bb",subgrid[{grp1obj,grp2obj}]}, now i am unable to assign data to main grid.Rematch
@Haider: Sorry, but I don't understand what you do and what you try to implement. Which version and which fork of jqGrid you use (or can use)? Do you use datatype: "local" or you load the data from the server? What colModel you use? You should open new question and describe everything in details.Irreverence
@Irreverence i am using datatype: "local" , my data is in format used for creating simple grid i can apply grouping to it by using group field "code" , but i want to use the data to create subgrid instead of groupsRematch
@Haider: What is your current problem? I repeat the previous question: which version of jqGrid and from which fork (free jqGrid, Guriddo jqGrid JS or an old jqGrid in version <=4.7) you use (or can use)? How you defined colModel? What properties and columns are defined in subgrid, grp1obj, grp2obj? I can continue. It's really better if you describe your problem in detailed in the new question.Irreverence

© 2022 - 2024 — McMap. All rights reserved.