如何在jqgrid中保留当前行数据?

7

如何在重新打开网格或刷新页面时保留当前行?

Persisting jqGrid column preferences中的答案介绍了如何保存列宽和其他一些参数。

在这个答案的演示中,我点击了一些行并按下了F5。以前点击的行没有被突出显示。

如何在本地存储中保存/恢复当前行?

更新

如果应用程序中修改了jqGrid列结构并且用户再次从浏览器打开应用程序,则restorecolumnstate会创建无效的colmodel,其中缺少某些元素。这会导致refreshSearchingToolbar中发生异常,该函数假定所有colmodel元素都存在。

如何修复这个问题?如何检测修改后的colmodol,并在这种情况下不恢复colmodel?还是说restoreColumnState更新colModel以创建适当的数组?

** 更新2 **

如果myColumnsState.permutation包含空值$grid.jqGrid("remapColumns", myColumnsState.permutation, true)将创建无效的colmodel。这里是在remapColumns调用之前和之后立即从VS调试器中截取的屏幕截图。

enter image description here

之后:

after

我通过更改代码来解决了这个问题:

    if (isColState && myColumnsState.permutation.length > 0) {
        var i, isnull = false;
        for (i = 0; i < myColumnsState.permutation.length; i = i + 1) {
            if (myColumnsState.permutation[i] == null) {
                isnull = true;
                break;
            }
        }
        if (!isnull) {
            $grid.jqGrid("remapColumns", myColumnsState.permutation, true);
        }

这是最佳解决方案吗?
2个回答

8

我将之前的答案中有关保持jqGrid列偏好的代码与另一个答案中的代码相结合,其中我提出了实现行选择持久化的代码。需要注意的是,对于multiselect:true的情况,将使用所选行的id数组,其中包含所有已选择的行,即使这些行位于另一页。这非常实用且实现非常简单。因此,我发布了相应的功能请求,但至今未得到回复。

现在我可以展示两个演示: 第一个演示 使用 multiselect: true,以及 第二个演示 同样使用这段代码,但只能单选。

下面是我所使用的代码的最重要的部分。

有一件事很重要需要提醒: 你应该在每个页面中修改 myColumnStateName 的值,如果不修改,变量的值将包含在 localStorage 中列状态的名称。因此,如果你不更改名称,将共享不同表格的状态,可能会产生非常奇怪的效果。你可以考虑将当前页面的名称或 URL 构造的名称用作 myColumnStateName 的值。

var $grid = $("#list"),
    getColumnIndex = function (grid, columnIndex) {
        var cm = grid.jqGrid('getGridParam', 'colModel'), i, l = cm.length;
        for (i = 0; i < l; i++) {
            if ((cm[i].index || cm[i].name) === columnIndex) {
                return i; // return the colModel index
            }
        }
        return -1;
    },
    refreshSerchingToolbar = function ($grid, myDefaultSearch) {
        var postData = $grid.jqGrid('getGridParam', 'postData'), filters, i, l,
            rules, rule, iCol, cm = $grid.jqGrid('getGridParam', 'colModel'),
            cmi, control, tagName;

        for (i = 0, l = cm.length; i < l; i++) {
            control = $("#gs_" + $.jgrid.jqID(cm[i].name));
            if (control.length > 0) {
                tagName = control[0].tagName.toUpperCase();
                if (tagName === "SELECT") { // && cmi.stype === "select"
                    control.find("option[value='']")
                        .attr('selected', 'selected');
                } else if (tagName === "INPUT") {
                    control.val('');
                }
            }
        }

        if (typeof (postData.filters) === "string" &&
                typeof ($grid[0].ftoolbar) === "boolean" && $grid[0].ftoolbar) {

            filters = $.parseJSON(postData.filters);
            if (filters && filters.groupOp === "AND" && typeof (filters.groups) === "undefined") {
                // only in case of advance searching without grouping we import filters in the
                // searching toolbar
                rules = filters.rules;
                for (i = 0, l = rules.length; i < l; i++) {
                    rule = rules[i];
                    iCol = getColumnIndex($grid, rule.field);
                    if (iCol >= 0) {
                        cmi = cm[iCol];
                        control = $("#gs_" + $.jgrid.jqID(cmi.name));
                        if (control.length > 0 &&
                                (((typeof (cmi.searchoptions) === "undefined" ||
                                typeof (cmi.searchoptions.sopt) === "undefined")
                                && rule.op === myDefaultSearch) ||
                                  (typeof (cmi.searchoptions) === "object" &&
                                      $.isArray(cmi.searchoptions.sopt) &&
                                      cmi.searchoptions.sopt.length > 0 &&
                                      cmi.searchoptions.sopt[0] === rule.op))) {
                            tagName = control[0].tagName.toUpperCase();
                            if (tagName === "SELECT") { // && cmi.stype === "select"
                                control.find("option[value='" + $.jgrid.jqID(rule.data) + "']")
                                    .attr('selected', 'selected');
                            } else if (tagName === "INPUT") {
                                control.val(rule.data);
                            }
                        }
                    }
                }
            }
        }
    },
    saveObjectInLocalStorage = function (storageItemName, object) {
        if (typeof window.localStorage !== 'undefined') {
            window.localStorage.setItem(storageItemName, JSON.stringify(object));
        }
    },
    removeObjectFromLocalStorage = function (storageItemName) {
        if (typeof window.localStorage !== 'undefined') {
            window.localStorage.removeItem(storageItemName);
        }
    },
    getObjectFromLocalStorage = function (storageItemName) {
        if (typeof window.localStorage !== 'undefined') {
            return JSON.parse(window.localStorage.getItem(storageItemName));
        }
    },
    myColumnStateName = 'ColumnChooserAndLocalStorage2.colState',
    idsOfSelectedRows = [],
    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'),
                sortname: this.jqGrid('getGridParam', 'sortname'),
                sortorder: this.jqGrid('getGridParam', 'sortorder'),
                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);
    },
    myColumnsState,
    isColState,
    restoreColumnState = function (colModel) {
        var colItem, i, l = colModel.length, colStates, cmName,
            columnsState = getObjectFromLocalStorage(myColumnStateName);

        if (columnsState) {
            colStates = columnsState.colStates;
            for (i = 0; i < l; i++) {
                colItem = colModel[i];
                cmName = colItem.name;
                if (cmName !== 'rn' && cmName !== 'cb' && cmName !== 'subgrid') {
                    colModel[i] = $.extend(true, {}, colModel[i], colStates[cmName]);
                }
            }
        }
        return columnsState;
    },
    updateIdsOfSelectedRows = function (id, isSelected) {
        var index = idsOfSelectedRows.indexOf(id);
        if (!isSelected && index >= 0) {
            idsOfSelectedRows.splice(index, 1); // remove id from the list
        } else if (index < 0) {
            idsOfSelectedRows.push(id);
        }
    },
    firstLoad = true;

myColumnsState = restoreColumnState(cm);
isColState = typeof (myColumnsState) !== 'undefined' && myColumnsState !== null;
idsOfSelectedRows = isColState && typeof (myColumnsState.selectedRows) !== "undefined" ? myColumnsState.selectedRows : [];

$grid.jqGrid({
    // ... some options
    page: isColState ? myColumnsState.page : 1,
    search: isColState ? myColumnsState.search : false,
    postData: isColState ? { filters: myColumnsState.filters } : {},
    sortname: isColState ? myColumnsState.sortname : 'invdate',
    sortorder: isColState ? myColumnsState.sortorder : 'desc',
    onSelectRow: function (id, isSelected) {
        updateIdsOfSelectedRows(id, isSelected);
        saveColumnState.call($grid, $grid[0].p.remapColumns);
    },
    onSelectAll: function (aRowids, isSelected) {
        var i, count, id;
        for (i = 0, count = aRowids.length; i < count; i++) {
            id = aRowids[i];
            updateIdsOfSelectedRows(id, isSelected);
        }
        saveColumnState.call($grid, $grid[0].p.remapColumns);
    },
    loadComplete: function () {
        var $this = $(this), i, count;

        if (firstLoad) {
            firstLoad = false;
            if (isColState) {
                $this.jqGrid("remapColumns", myColumnsState.permutation, 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);
    },
    resizeStop: function () {
        saveColumnState.call($grid, $grid[0].p.remapColumns);
    }
});

$grid.jqGrid('navGrid', '#pager', {edit: false, add: false, del: false});
$grid.jqGrid('navButtonAdd', '#pager', {
    caption: "",
    buttonicon: "ui-icon-closethick",
    title: "clear saved grid's settings",
    onClickButton: function () {
        removeObjectFromLocalStorage(myColumnStateName);
        window.location.reload();
    }
});
更新: 我忘记提到,在使用 jqGrid 4.3 的 multiselect: true 选项时,非常重要的是使用这个修复程序,在这里进行了描述。在第一个演示中,我使用了包含错误修复的 jquery.jqGrid.src.js修改版本更新2: 为了方便生成用于保存网格状态的本地存储项的唯一名称,我稍微修改了演示。多选演示单选演示的下一个版本将使用myColumnStateName作为以下函数的定义。请注意保留HTML标签。
var myColumnStateName = function (grid) {
        return window.location.pathname + '#' + grid[0].id;
    }

myColumnStateName的使用相应地发生了变化。此外,我扩展了列状态以保存rowNum值。

更新3:答案描述了如何使用free jqGrid的新功能来保存网格状态。


从http://www.trirand.com/blog/?page_id=393/bugs/exception-after-successful-delete-in-complete-event-handler获取的关键补丁未应用。每次成功的远程删除都会导致异常。 - Andrus
@Andrus:在我发布的演示中,没有删除、添加或编辑操作。您可以尝试一下,不会抛出任何异常。 - Oleg
如果仅按分页导航按钮,则不会保存当前页面编号和页面大小。 - Andrus
1
@Andrus:为了减少在页面上有多个网格的情况下如何使用myColumnStateName的误解,我稍微修改了演示文稿。此外,我扩展了列状态以保存rowNum值。 - Oleg
1
var cm = $grid.jqGrid('getGridParam', 'colModel')替换null检查,然后检查 && myColumnsState.permutation.length == cm.length,似乎可以解决这个问题。 - Andrus
显示剩余19条评论

4

当你刷新页面时,Oleg的解决方案会产生以下错误。

错误: 未捕获的类型错误:无法读取未定义的属性 'el'

行: jquery.jqGrid.src.js中的1936

var previousSelectedTh = ts.grid.headers[ts.p.lastsort].el, newSelectedTh = ts.grid.headers[idxcol].el;

解决方法是保存lastsort网格参数,并在加载完成时重置它,如下所示。
saveColumnState = function(perm) {
...
  columnsState = {
    search: this.jqGrid('getGridParam', 'search'),
    page: this.jqGrid('getGridParam', 'page'),
    sortname: this.jqGrid('getGridParam', 'sortname'),
    sortorder: this.jqGrid('getGridParam', 'sortorder'),
    lastsort: this.jqGrid('getGridParam', 'lastsort'),
    permutation: perm,
    colStates: { }
  },
...
},

loadComplete: function(data) {
...
  if (isColState) {
    $this.jqGrid("remapColumns", myColumnsState.permutation, true);
    if(myColumnsState.lastsort > -1)
      $this.jqGrid("setGridParam", { lastsort: myColumnsState.lastsort });
  }
...
},

刚遇到这个问题 - 感谢您节省了我几个小时的调试时间 :) - Charles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接