Is it possible to modify the colModel after data has loaded with jqgrid?

前端 未结 1 1554
忘掉有多难
忘掉有多难 2020-11-30 13:29

I\'ve got a jqGrid where I need to change the model after the data is loaded, but before it\'s parsed into the grid. In otherwords, I think I want to do it in the loadComple

相关标签:
1条回答
  • 2020-11-30 13:58

    I found one way which seems work OK.

    The idea of my solution is following. You use colModel having many hidden columns with the dummy names like 'cm0', 'cm1', 'cm2', ... All the columns has the same data like you need in your case. To fill the data more easy I use column templates existing since jqGrid 3.8.2:

    var mygrid=jQuery("#list"),
        cmIntTemplate = {
            width:50,
            sorttype:"int",
            formatter:"integer",
            align:"right",
            hidden:true
        },
        cm = [
            // here we define the first columns which we always has
            // the list can be empty or has some columns with
            // the properties other as the rest (without cmIntTemplate)
            {name:"date",label:"Date",key:true,width:100, fixed:true,
             formatter:'date',formatoptions:{srcformat:"m-d",newformat:"m/d"}}
        ], maxCol = 30, dummyColumnNamePrefix = "cm";
    
    // Add dummy hidden columns. All the columns has the same template
    for (i=0;i<maxCol;i++) {
        cm.push({name:dummyColumnNamePrefix+i,template:cmIntTemplate});
    }
    

    After that I create jqGrid in the standard way, but with the jsonReader which use the page as function:

    jsonReader: {
        repeatitems: false,
        page: function (obj) {
            // ------------------------
            // here I add the main code
            // ------------------------
            return obj.page;
        }
    }
    

    The function from the jsonReader.page return the same value like as do default jsonReader, but I use the way with function because the function will be called directly before the reading of the main contain of JSON data. Inside of the code I get the first row of the data and use it's property names to fill jsonmap property of the corresponding column and set the column name. Additionally I make some dummy columns needed to display all the JSON data visible and the rest dummy column hidden. The last thing which should be done is correction of the grid width which was calculated previously. So the grid will look like this:

    enter image description here

    or like this

    enter image description here

    depend on the JSON input data.

    The code of the page function is following:

    page: function (obj) {
        var rows = obj.rows, colModel = mygrid[0].p.colModel,
            cmi, iFirstDummy, firstRow, prop,
            orgShrinkToFit, isFound,
            showColNames = [], hideColNames = [];
    
        if (typeof(rows) === "undefined" || !$.isArray(rows) || rows.length === 0) {
            // something wrong need return
            return obj.page;
        }
    
        // find the index of the first dummy column
        // in the colModel. If we use rownumbers:true,
        // multiselect:true or subGrid:true additional
        // columns will be inserted at the begining
        // of the colModel
        iFirstDummy = -1;
        for(i=0;i<colModel.length;i++) {
            cmi = colModel[i];
            if (dummyTestRegex.test(cmi.name)) {
                iFirstDummy = i;
                break;
            }
        }
        if (iFirstDummy === -1) {
            // something wrong need return
            return obj.page;
        }
    
        orgShrinkToFit = clearShrinkToFit();
    
        // we get the first row of the JSON data
        firstRow = rows[0];
        for (prop in firstRow) {
            if (firstRow.hasOwnProperty(prop)) {
                // we will use the properties name of the first row
                // as the names of the column headers of the grid
    
                // find column index having prop as the name
                isFound = false;
                for(i=0;i<colModel.length;i++) {
                    cmi = colModel[i];
                    if (cmi.name === prop) {
                        isFound = true;
                        showColNames.push(prop);
                        break;
                    }
                }
                if(!isFound) {
                    // labels defines the column names
                    cmi = colModel[iFirstDummy];
                    showColNames.push(cmi.name);
                    mygrid.jqGrid('setLabel',cmi.name,prop);
    
                    // because of bug in jqGrid with calculation of width
                    // we have to reset the width
                    cmi.width = cmIntTemplate.width;
    
                    // we set jsonmap which jqGrid will use instead
                    // of dummy column names to read all row data
                    cmi.jsonmap = prop;
                    iFirstDummy++;
                }
            }
        }
    
        // fill the list of unused columns
        for(i=0;i<colModel.length;i++) {
            cmi = colModel[i];
            if ($.inArray(cmi.name, showColNames) === -1 && dummyTestRegex.test(cmi.name)) {
                hideColNames.push(cmi.name);
            }
        }
        mygrid.jqGrid('showCol',showColNames);
        mygrid.jqGrid('hideCol',hideColNames);
    
        setGridWidthAndRestoreShrinkToFit(orgShrinkToFit);
    
        return obj.page;
    }
    

    Inside of the page function I use small helper functions

    var clearShrinkToFit = function() {
            // save the original value of shrinkToFit
            var orgShrinkToFit = mygrid.jqGrid('getGridParam','shrinkToFit');
            // set shrinkToFit:false to prevent shrinking
            // the grid columns after its showing or hiding
            mygrid.jqGrid('setGridParam',{shrinkToFit:false});
            return orgShrinkToFit;
        },
        setGridWidthAndRestoreShrinkToFit = function(orgShrinkToFit) {
            // calculate the new grid width
            var width=0, i=0, headers=mygrid[0].grid.headers, l=headers.length;
            for (;i<l; i++) {
                var th = headers[i].el;
                if (th.style.display !== "none") {
                    width += $(th).outerWidth();
                }
            }
    
            // restore the original value of shrinkToFit
            mygrid.jqGrid('setGridParam',{shrinkToFit:orgShrinkToFit});
    
            // set the grid width
            mygrid.jqGrid('setGridWidth',width);
        },
        dummyTestRegex = new RegExp(dummyColumnNamePrefix+"(\\d)+");
    

    The working demo you can see here.

    UPDATED: Another answer with the demo shows how to create the grid which has another format of input data: [[], [], ...] (array of arrays) - matrix.

    0 讨论(0)
提交回复
热议问题