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

2022-01-19 00:00:00 jquery javascript jqgrid free-jqgrid

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

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

is used to save jqgrid state. It saves jqgrid column state using column numbers. If jqgrid colmodel is changed in server, this causes javascript error in browser.

冻结 JQGrid 中的 rownum 列 评论和 https://github.com/free-jqgrid/jqGrid/blob/master/README49.md 描述方法 remapColumnsByName .我希望使用它来解决问题.

Freeze rownum column in JQGrid comment and https://github.com/free-jqgrid/jqGrid/blob/master/README49.md describes method remapColumnsByName . I hoped that using this fixes the issUe.

free jqgrid 是从今天的 git master 下载的.调整列大小或移动行后处于状态保存

free jqgrid was downloaded from todays git master. In state save after columns was resized or moved line

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

改为

saveColumnState.call($grid, $grid[0].p.remapColumnsByName);

并在 loadComplete 代码中恢复状态

and in state restore in loadComplete code

    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

如何解决这个问题,以便在更改列定义时可以使用列状态?

How to fix this so that column state can can used if column definition is changed?

方法定义为

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

推荐答案

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

First of all I want to mention that the code described in the old answer works not always correct. To explain the problem you can open the single row select demo for example and uses column chooser multiple times before reloading the grid. For example you can open column chooser first and change position of "Clients" column after "Tax" column. You will see correct results in the grid. Then you can open column chooser once more and move "Date" column after "Clients" column for example. You will see the columns in the order "Amount", "Tax", "Client", "Date", ... Now you can reload the page. You will see that the reloaded page have wrong order of columns: "Client", "Amount", "Tax", "Date", ... The reason on the problem: permutation used by column chooser or by remapColumns uses integer position of columns relatively to current order of columns. It makes saving of column order more complex. One have to hold original column order and recalculates always the values from permutation array to reordering of original colModel.

或者,可以保存列名,而不是相对于原始列模型更改列位置的数组.换句话说,应该将 columnsStatepermutation 属性替换为类似于 cmOrder 的东西,其中包含网格中的列名数组,该数组上次选择了用户.

Alternatively one can saves column names instead of arrays with changed column position relatively to original column model. In other words one should replace permutation property of columnsState to something like cmOrder with array of column names in the grid, which choosed the user last time.

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

The method remapColumnsByName is very simple. It works like the method remapColumns, but its first parameter is array of column names instead of array of integer indexes.

演示是快速而肮脏的单曲更换行选择演示使用 cmOrder 属性而不是 columnsState 中的 permutation 属性,并另外使用方法 remapColumnsByName.如果您像我在答案开头描述的那样重复相同的测试,您会发现新的演示没有我之前描述的错误.

The demo is quick and dirty changing of the single row select demo to use cmOrder property instead of permutation property in columnsState and to use the method remapColumnsByName additionally. If you would repeat the same test like I described at the beginning of my answer you will see that new demo don't have the bug which I described before.

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

The most important parts of the demo which is different from original demo you will find below:

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回调如下

moreover the loadComplete callback which restore the order of the columns is the following

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 方法.

I want to repeat that the code from the new demo is far from be perfect. I just used the old code and fixed it to make it working in free jqGrid and by using new remapColumnsByName method.

相关文章