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

IT技术 javascript jquery jqgrid free-jqgrid
2021-01-25 15:26:02

来自如何在 jqgrid 中保留当前行的答案的代码

用于保存 jqgrid 状态。它使用列号保存 jqgrid 列状态。如果在服务器中更改 jqgrid colmodel,这会导致浏览器中的 javascript 错误。

冻结 JQGrid评论中的rownum 列https://github.com/free-jqgrid/jqGrid/blob/master/README49.md描述方法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 &&
                      myColumnsState.permutation.length === cm.length) {
        $grid.jqGrid("remapColumnsByName", 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));
    }
};
1个回答

首先,我想提一下,旧答案中描述的代码并不总是正确的。为了解释这个问题,您可以打开单行选择演示,例如,在重新加载网格之前多次使用列选择器例如,您可以先打开列选择器,然后在“税务”列之后更改“客户”列的位置。您将在网格中看到正确的结果。然后您可以再次打开列选择器并将“日期”列移动到“客户”列之后。您将看到按“金额”、“税”、“客户”、“日期”等顺序排列的列……现在您可以重新加载页面。您将看到重新加载的页面的列顺序错误:“客户”、“金额”、“税收”、“permutationremapColumns列的整数位置相对于当前列的顺序它使列顺序的保存更加复杂。必须保持原始列顺序并始终重新计算permutation数组中的值以重新排序original colModel

或者,可以保存列名而不是相对于原始列模型更改了列位置的数组。换句话说,应该用上次选择用户的网格中的列名数组替换to 的permutation属性columnsStatecmOrder

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

该演示是单行选择演示的快速而肮脏的更改,以使用cmOrder属性而不是permutation属性 incolumnsStateremapColumnsByName额外使用该方法如果您像我在回答开头所描述的那样重复相同的测试,您会发现新演示没有我之前描述的错误。

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

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,恢复列顺序回调如下

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);
},

我想重复一遍,新演示中的代码远非完美。我只是使用旧代码并修复它以使其在免费的 jqGrid 中工作并使用新remapColumnsByName方法。

jshint 建议将此更改为!==所以我更改了它。我通过&& typeof myColumnsState.cmOrder !== "undefined"stackoverflow.com/questions/29194381/...评论中添加喜欢来修复它
2021-03-16 15:26:02
@Andrus:有很多建议。例如,jQuery 样式指南说明以下内容(请参阅此处):“必须使用严格的相等性检查 (===) 来支持抽象的相等性检查 (==)。唯一的例外是通过 null 检查 undefined 和 null .” jqGrid 代码遵循规则。jshint 可以为case 配置参数。
2021-03-17 15:26:02
@Andrus:我的代码有myColumnsState.cmOrder != null而不是myColumnsState.cmOrder !== null. != null是测试nullundefined这一点很重要!
2021-03-30 15:26:02
@user3662273:版本 4.4.4 中不存在 remapColumnsByName 方法。它存在于从 4.9.0 版开始的免费 jqGrid fork 中。
2021-04-07 15:26:02
问题仍然存在:有时行if (isColState && myColumnsState.cmOrder !== null && myColumnsState.cmOrder.length > 0)返回错误Uncaught TypeError: Cannot read property 'length' of undefined页面保持禁用状态,无法访问。如何解决这个问题,这个检查可以改进吗?
2021-04-09 15:26:02