asp.net mvc - 持久化jqGrid列首选项



asp.net-mvc asp.net-mvc-3 (1)

我的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列中的任何一列。

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


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

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

电网状态的另一个问题是维护。 有关您所持有的网格列的信息通常位于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不能用于保存太多信息。 例如,如果要保存每个网页的每个网格的状态,则可以快速达到限制。

另一方面, 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,但它更好的是4K用于cookie(见here )。

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

this演示中,网格的以下状态将被保存并在页面重新加载时自动恢复(大多数Web浏览器中为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'`)定义为不同页面上的不同值。

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

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





jqgrid