Javascript 如何在免费jqgrid中用remapColumnsByName替换remapColums

Javascript 如何在免费jqgrid中用remapColumnsByName替换remapColums,javascript,jquery,jqgrid,free-jqgrid,Javascript,Jquery,Jqgrid,Free Jqgrid,答案中的代码 用于保存jqgrid状态。它使用列编号保存jqgrid列状态。若在服务器中更改了jqgrid colmodel,则会导致浏览器中出现javascript错误 注释并描述方法remapColumnsByName。我希望用这个方法可以解决这个问题 免费jqgrid是从今天的git master下载的。 列被调整大小或移动到行后处于保存状态 saveColumnState.call($grid, $grid[0].p.remapColumns); 改为 saveColumnState.

答案中的代码

用于保存jqgrid状态。它使用列编号保存jqgrid列状态。若在服务器中更改了jqgrid colmodel,则会导致浏览器中出现javascript错误

注释并描述方法
remapColumnsByName
。我希望用这个方法可以解决这个问题

免费jqgrid是从今天的git master下载的。 列被调整大小或移动到行后处于保存状态

saveColumnState.call($grid, $grid[0].p.remapColumns);
改为

saveColumnState.call($grid, $grid[0].p.remapColumnsByName);
并在loadComplete代码中进行状态恢复

    if (isColState && myColumnsState.permutation.length > 0 &&
                      myColumnsState.permutation.length === cm.length) {
        $grid.jqGrid("remapColumns", myColumnsState.permutation, true);

    }

现在排队

 if (isColState && myColumnsState.permutation.length > 0 &&
导致错误

Uncaught TypeError: Cannot read property 'length' of undefined
如何解决此问题,以便在更改列定义时可以使用列状态

方法定义为

var saveColumnState = function (perm) {
    var colModel = this.jqGrid('getGridParam', 'colModel'),
        i, l = colModel.length, colItem, cmName,
        postData = this.jqGrid('getGridParam', 'postData'),
        columnsState = {
            search: this.jqGrid('getGridParam', 'search'),
            page: this.jqGrid('getGridParam', 'page'),
            rowNum: this.jqGrid('getGridParam', 'rowNum'),
            sortname: this.jqGrid('getGridParam', 'sortname'),
            sortorder: this.jqGrid('getGridParam', 'sortorder'),
            autoedit: autoedit,
            rownumbers: $grid.jqGrid('getGridParam', 'rownumbers') && !$grid[0].p.colModel[0].hidden,

            searchWindow: searchParams,
            editWindow: editParams,
            permutation: perm,
            selectedRows: idsOfSelectedRows,
            colStates: {}
        },
        colStates = columnsState.colStates;

    if (typeof (postData.filters) !== 'undefined') {
        columnsState.filters = postData.filters;
    }

    for (i = 0; i < l; i++) {
        colItem = colModel[i];
        cmName = colItem.name;
        if (cmName !== 'rn' && cmName !== 'cb' && cmName !== 'subgrid') {
            colStates[cmName] = {
                width: colItem.width,
                hidden: colItem.hidden
            };
        }
    }
    saveObjectInLocalStorage(myColumnStateName, columnsState);
};

var saveObjectInLocalStorage = function (storageItemName, object) {
    if (typeof window.localStorage !== 'undefined') {
        window.localStorage.setItem(storageItemName, JSON.stringify(object));
    }
};
var saveColumnState=函数(perm){
var colModel=this.jqGrid('getGridParam','colModel'),
i、 l=colModel.length,colItem,cmName,
postData=this.jqGrid('getGridParam','postData'),
列状态={
搜索:this.jqGrid('getGridParam','search'),
page:this.jqGrid('getGridParam','page'),
rowNum:this.jqGrid('getGridParam','rowNum'),
sortname:this.jqGrid('getGridParam','sortname'),
sortorder:this.jqGrid('getGridParam','sortorder'),
自动编辑:自动编辑,
行数:$grid.jqGrid('getGridParam','rownumbers')&&!$grid[0]。p.colModel[0]。隐藏,
searchWindow:searchParams,
editWindow:editParams,
排列:排列,
selectedRows:idsOfSelectedRows,
colStates:{}
},
colStates=columnsState.colStates;
if(typeof(postData.filters)!=‘未定义’){
columnsState.filters=postData.filters;
}
对于(i=0;i
首先,我想指出,旧答案中描述的代码并不总是正确的。要解释此问题,您可以在重新加载网格之前打开并多次使用列选择器。例如,您可以先打开列选择器,然后在“Tax”列之后更改“Clients”列的位置。您将在网格中看到正确的结果。然后,您可以再次打开列选择器,并将“日期”列移到“客户”列之后,例如。您将看到“金额”、“税款”、“客户”、“日期”和。。。现在可以重新加载页面了。您将看到重新加载的页面的列顺序错误:“客户”、“金额”、“税款”、“日期”。。。问题的原因是:
permutation
由列选择器或
remapColumns
使用的列相对于当前列顺序的整数位置。这使得列顺序的保存更加复杂。必须保持原始列顺序,并始终重新计算从
排列
数组到原始
colModel
重新排序的值

或者,可以保存列名,而不是相对于原始列模型更改了列位置的数组。换言之,应该将
columnsState
permutation
属性替换为类似
cmOrder
的内容,使用网格中的列名数组,该数组上次选择了用户

方法
remapColumnsByName
非常简单。它的工作原理类似于方法
remapColumns
,但它的第一个参数是列名数组,而不是整数索引数组

是否快速而肮脏地更改单行选择演示以使用
cmOrder
属性而不是
columnsState
中的
permutation
属性,并另外使用方法
remapColumnsByName
。如果你像我在回答开始时描述的那样重复相同的测试,你会看到新的演示没有我之前描述的bug

演示中最重要的部分与原始演示不同,您可以在下面找到:

var getColumnNamesFromColModel = function () {
        var colModel = this.jqGrid("getGridParam", "colModel");
        return $.map(colModel, function (cm, iCol) {
            // we remove "rn", "cb", "subgrid" columns to hold the column information 
            // independent from other jqGrid parameters
            return $.inArray(cm.name, ["rn", "cb", "subgrid"]) >= 0 ? null : cm.name;
        });
    },
    saveColumnState = function () {
        var p = this.jqGrid("getGridParam"), colModel = p.colModel, i, l = colModel.length, colItem, cmName,
            postData = p.postData,
            columnsState = {
                search: p.search,
                page: p.page,
                rowNum: p.rowNum,
                sortname: p.sortname,
                sortorder: p.sortorder,
                cmOrder: getColumnNamesFromColModel.call(this),
                selectedRows: idsOfSelectedRows,
                colStates: {}
            },
            colStates = columnsState.colStates;

        if (postData.filters !== undefined) {
            columnsState.filters = postData.filters;
        }

        for (i = 0; i < l; i++) {
            colItem = colModel[i];
            cmName = colItem.name;
            if (cmName !== "rn" && cmName !== "cb" && cmName !== "subgrid") {
                colStates[cmName] = {
                    width: colItem.width,
                    hidden: colItem.hidden
                };
            }
        }
        saveObjectInLocalStorage(myColumnStateName(this), columnsState);
    },
    ...

我想重复一次,新演示的代码远远不够完美。我只是使用了旧代码,并通过使用新的
remapColumnsByName
方法修复了它,使其在免费jqGrid中工作。

问题仍然存在:有时行
if(isColState&&myColumnsState.cmOrder!==null&&myColumnsState.cmOrder.length>0)
返回错误
未捕获类型错误:无法读取未定义的属性“length”
。页面仍处于禁用状态,无法访问。如何解决这个问题,这个检查能改进吗?@Andrus:我的代码有
myColumnsState.cmOrder!=null
而不是myColumnsState.cmOrder!==空<代码>!=null是针对
null
未定义的
的测试。这很重要!jshint建议将此更改为
==所以我改变了它。我通过添加myColumnsState.cmOrder!==“未定义”
与中类似comment@Andrus:有很多建议。例如,jQuery style guide说(请参阅):“必须使用严格的相等性检查(==)来支持抽象相等性检查(==)。唯一的例外是通过null检查未定义和null。”jqGrid代码遵循该规则。jshint可以为该案例配置参数。@user3662273:remapColumnsByName方法在4.4.4版中不存在。它存在于从版本4.9.0开始的fork中。
var getColumnNamesFromColModel = function () {
        var colModel = this.jqGrid("getGridParam", "colModel");
        return $.map(colModel, function (cm, iCol) {
            // we remove "rn", "cb", "subgrid" columns to hold the column information 
            // independent from other jqGrid parameters
            return $.inArray(cm.name, ["rn", "cb", "subgrid"]) >= 0 ? null : cm.name;
        });
    },
    saveColumnState = function () {
        var p = this.jqGrid("getGridParam"), colModel = p.colModel, i, l = colModel.length, colItem, cmName,
            postData = p.postData,
            columnsState = {
                search: p.search,
                page: p.page,
                rowNum: p.rowNum,
                sortname: p.sortname,
                sortorder: p.sortorder,
                cmOrder: getColumnNamesFromColModel.call(this),
                selectedRows: idsOfSelectedRows,
                colStates: {}
            },
            colStates = columnsState.colStates;

        if (postData.filters !== undefined) {
            columnsState.filters = postData.filters;
        }

        for (i = 0; i < l; i++) {
            colItem = colModel[i];
            cmName = colItem.name;
            if (cmName !== "rn" && cmName !== "cb" && cmName !== "subgrid") {
                colStates[cmName] = {
                    width: colItem.width,
                    hidden: colItem.hidden
                };
            }
        }
        saveObjectInLocalStorage(myColumnStateName(this), columnsState);
    },
    ...
loadComplete: function () {
    var $this = $(this), p = $this.jqGrid("getGridParam"), i, count;

    if (firstLoad) {
        firstLoad = false;
        if (isColState && myColumnsState.cmOrder != null && myColumnsState.cmOrder.length > 0) {
            // We compares the values from myColumnsState.cmOrder array
            // with the current names of colModel and remove wrong names. It could be
            // required if the column model are changed and the values from the saved stated
            // not corresponds to the 
            var fixedOrder = $.map(myColumnsState.cmOrder, function (name) {
                    return p.iColByName[name] === undefined ? null : name;
                });
            $this.jqGrid("remapColumnsByName", fixedOrder, true);
        }
        if (typeof (this.ftoolbar) !== "boolean" || !this.ftoolbar) {
            // create toolbar if needed
            $this.jqGrid("filterToolbar",
                {stringResult: true, searchOnEnter: true, defaultSearch: myDefaultSearch});
        }
    }
    refreshSerchingToolbar($this, myDefaultSearch);
    for (i = 0, count = idsOfSelectedRows.length; i < count; i++) {
        $this.jqGrid("setSelection", idsOfSelectedRows[i], false);
    }
    saveColumnState.call($this, this.p.remapColumns);
},