持久化jqGrid列首选项

its*_*att 27 asp.net-mvc jqgrid asp.net-mvc-3

我的ASP.NET MVC 3应用程序上有一些jqGrids,它们有很多列.我在列定义中添加了以下内容,以默认隐藏一些列:

colModel: [
   { name: 'IceCreamID', hidden: true},
   { name: 'RecipeID', hidden: true }
Run Code Online (Sandbox Code Playgroud)

这很好用.这些列在我的网格上不可见.

然后我添加了这个来实现列选择器:

var grid = $('#icecreamGrid');
grid.jqGrid('navButtonAdd', '#icecreamPager',
{ caption: "Columns", buttonicon: "ui-icon-calculator",
  title: "Choose Columns",
  onClickButton: function() {
     grid.jqGrid('columnChooser');
  }
});
Run Code Online (Sandbox Code Playgroud)

太棒了,现在提出了专栏选择器.然后我将以下内容添加到我从未希望在列选择器中显示的列中:

colModel: [
   { name: 'IceCreamID', hidden: true, hidedlg: true},
Run Code Online (Sandbox Code Playgroud)

所以我现在可以隐藏/显示列就好了.现在,您如何坚持这些信息?D B?作为一个cookie?另一种方式?是否有一种首选的方式来存储这种真正是用户偏好的信息,而不是与数据本身相关的信息?


更多信息

根据Oleg在下面的评论,我想提供更多信息.

这里的要点是我有10-15列的网格,可以根据用户的偏好显示.举一个简单的例子,我的一个网格有以下9列:

IceCream|ShortName|HasNuts|SugarAdded|LimitedRun|PromoItem|Facility|FirstRun|LastRun
Run Code Online (Sandbox Code Playgroud)

用户可以根据个人喜好隐藏/显示这9列中的任何一列.

我想要做的是提供一种方法来持久保存特定用户想要查看的列,以便他/她不必在每次显示带有该网格的页面时重新选择这些列.

Ole*_*leg 41

我发现你的问题非常有趣.在许多情况下,关于保存网格的用户状态的问题很有意思.关于使用cookie的这些问题有一些有趣的答案(例如参见这里).

在我看来,在服务器上保存数据库中的网格状态,或者localStorage更好的方式是使用cookie.最好的方法取决于项目使用它的要求.例如,在服务器上使用数据库存储允许您实现网格的漫游状态.如果您使用localStorage而不是cookie,如果用户转到另一台计算机或用户将在同一台计算机上使用其他Web浏览器,则用户首选项将丢失.

电网状态的另一个问题是维护.有关您保存的网格列的信息通常位于JavaScript或HTML文件中,而不是数据库中.在这种情况下,两个源可以不同步网格中的变化.您可以轻松想象更新问题的不同情况.然而,在某些情况下用户偏好的优点如此之大,以至于小缺点的问题不那么重要并且可以相对容易地解决.

所以我会花一些时间来实现两个演示,展示如何实现它.localStorage由于种种原因,我在演示中使用过.我只提到两个:

  1. Cookie是向服务器发送永久不同信息的方式,而不是真正需要的服务器.它会增加HTTP标头的大小并降低网站的性能(例如,请参见此处).
  2. Cookie有很严格的限制.对应rfc2109的6.3节或rfc6265的6.1节:每个cookie至少4096字节,每个域至少50个cookie(rfc2109中20个),总共至少3000个cookie(rfc2109中300个).所以cookie不能用来保存太多的信息.例如,如果要保存每个网页的每个网格的状态,则可以快速达到限制.

另一方面localStorage,所有现代浏览器都支持,IE8开始支持IE8(参见此处).该localStorage会每起源自动保存(如a1.example.com,a2.example.com,a3.example.com等),并为每原点5 MB(见任意限制这里).因此,如果您仔细使用空间,您将远离任何限制.

所以我在我的演示中使用了localStorage.我还应该提一下,有一些像jStorage这样的插件,localStorage如果浏览器支持它并使用另一个存储器,则使用它,但是对于IE6/IE7等旧浏览器,你可以使用相同的界面.在这种情况下,你只有更少的存储空间:128 kB而不是5 MB,但它更好的是4K用于cookie(见这里).

现在关于实施.我创建了两个演示:这个和它的扩展版本:这个.

第一个演示中,网格的以下状态将被保存并在页面重新加载时自动恢复(F5在大多数Web浏览器中):

  • 哪一列是隐藏的
  • 列的顺序
  • 每列的宽度
  • 将对网格进行排序的列的名称以及排序方向
  • 当前页码
  • 网格的当前过滤器和标志是否应用过滤器.我multipleSearch: true在网格中使用了设置.

以同样的方式,可以扩展(或减少)作为保存的网格状态的一部分的选项列表.

以下是演示代码中最重要的部分:

var $grid = $("#list"),
    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 $.parseJSON(window.localStorage.getItem(storageItemName));
        }
    },
    myColumnStateName = 'ColumnChooserAndLocalStorage.colState',
    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,
                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;
    },
    firstLoad = true;

myColumnsState = restoreColumnState(cm);
isColState = typeof (myColumnsState) !== 'undefined' && myColumnsState !== null;

$grid.jqGrid({
    // ... other 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',
    loadComplete: function () {
        if (firstLoad) {
            firstLoad = false;
            if (isColState) {
                $(this).jqGrid("remapColumns", myColumnsState.permutation, true);
            }
        }
        saveColumnState.call($(this), this.p.remapColumns);
    }
});
$grid.jqGrid('navButtonAdd', '#pager', {
    caption: "",
    buttonicon: "ui-icon-calculator",
    title: "choose columns",
    onClickButton: function () {
        $(this).jqGrid('columnChooser', {
            done: function (perm) {
                if (perm) {
                    this.jqGrid("remapColumns", perm, true);
                    saveColumnState.call(this, perm);
                }
            }
        });
    }
});
$grid.jqGrid('navButtonAdd', '#pager', {
    caption: "",
    buttonicon: "ui-icon-closethick",
    title: "clear saved grid's settings",
    onClickButton: function () {
        removeObjectFromLocalStorage(myColumnStateName);
    }
});
Run Code Online (Sandbox Code Playgroud)

小心地将myColumnStateName(在演示中的值''ColumnChooserAndLocalStorage.colState'`)定义为不同页面上的不同值.

第二个演示是使用我的旧答案中的技巧扩展第一个演示到另一个问题.该演示使用搜索工具栏并在高级搜索表单和搜索工具栏之间同步其他信息.

更新:下一个答案包含上面包含的代码的扩展版本.它显示了如何另外保留选定的行(或行).另一个答案显示了如何持久保存树网格的扩展节点列表并在页面重新编码时扩展节点.

  • @Andrus:看看我最近的另一个[答案](http://stackoverflow.com/a/9045125/315935),它显示了如何监控列的重新排序.一个人应该在`sortable`里面调用`saveColumnState`定义为函数. (2认同)