持久化jqGrid列首选项

时间:2011-12-07 21:32:22

标签: asp.net-mvc asp.net-mvc-3 jqgrid

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

colModel: [
   { name: 'IceCreamID', hidden: true},
   { name: 'RecipeID', hidden: true }

这很好用。这些列在我的网格中不可见。

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

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

很好,现在调出列选择器。然后我将以下内容添加到我从未希望在列选择器中显示的列中:

colModel: [
   { name: 'IceCreamID', hidden: true, hidedlg: true},

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


更多信息

根据Oleg的评论,我想提供更多信息。

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

IceCream|ShortName|HasNuts|SugarAdded|LimitedRun|PromoItem|Facility|FirstRun|LastRun

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

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

1 个答案:

答案 0 :(得分:41)

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

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

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

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

  1. Cookie是向服务器发送永久不同信息的方式,而不是真正需要的服务器。它会增加HTTP标头的大小并降低网站的性能(例如,请参阅here)。
  2. Cookie有很严格的限制。对应于rfc2109的6.3部分或rfc6265的6.1:每个cookie至少4096个字节,每个域至少50个cookie(rfc2109中为20个),总共至少3000个cookie(rfc2109中为300个)。所以cookie不能用来保存太多的信息。例如,如果要保存每个网页的每个网格的状态,就可以快速达到限制。
  3. 另一方面localStorage受到所有现代浏览器的支持,并且从IE8开始支持Internet Explorer(请参阅here)。 localStorage将自动保存为每个来源(例如a1.example.com,a2.example.com,a3.example.com等),并且每个来源的任意限制为5 MB(请参阅here )。因此,如果你仔细使用这个空间,你将远离任何限制。

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

    现在关于实施。我创建了两个演示:this,它的扩展版本为:this

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

    • 隐藏哪一列
    • 列的顺序
    • 每列的宽度
    • 将对网格进行排序的列的名称和排序方向
    • 当前页码
    • 网格的当前过滤器和标志是否应用过滤器。我在网格中使用了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);
        }
    });
    

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

    The second demo是第一个使用我的old answer中的技术到您的另一个问题的扩展。该演示使用搜索工具栏并在高级搜索表单和搜索工具栏之间同步其他信息。

    更新next answer包含上面包含的代码的扩展版本。它显示了如何另外保留选定的行(或行)。 Another answer显示如何持久保存树网格的扩展节点列表,并在页面重新编码时展开节点。