持久化 jqGrid 列首选项 [英] Persisting jqGrid column preferences

查看:32
本文介绍了持久化 jqGrid 列首选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've got a few jqGrids on my ASP.NET MVC 3 application that have a number of columns. I added the following to the column definitions to default some columns to be hidden:

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

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

and this works nicely. Those columns aren't visible on my grid.

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

Then I added this to implement the column chooser:

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

太好了,现在调出列选择器.然后,我将以下内容添加到我不想在列选择器中显示的列中:

Great, brings up the column chooser now. I then added the following to columns I never wanted to show up in the column chooser:

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

所以我现在可以很好地隐藏/显示列.现在,您将如何保留这些信息?D B?作为饼干?另一种方式?有没有一种首选方式来存储这种真正属于用户偏好的信息,而不是与数据本身相关的信息?

So I can now hide/show columns just fine. Now, how would you persist this information? DB? As a cookie? Other way? Is there a preferred way to store this sort of information that is really a user preference rather than something related to the data itself?

更多信息

根据下面奥列格的评论,我想提供更多信息.

Based on Oleg's comment below, I want to provide a little more information.

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

The point here is that I've got grids with 10-15 columns which could be display based on the user's preference. For a simple example, one of my grid's has the following 9 columns:

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

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

Users can hide/show any of these 9 columns based on their personal preferences.

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

What I want to do is provide a way to persist which columns a particular user wants to see so that s/he doesn't have to re-choose those columns to view each time the page with that grid is shown.

推荐答案

我发现你的问题很有趣.在很多情况下,关于保存网格的用户状态的问题很有趣.对于使用 cookie 的此类问题,有一些有趣的答案(例如,参见 此处).

I found you question very interesting. The question about saving the user state of grid are interesting in many cases. There are some interesting answers on such problems which uses cookie (see here for example).

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

In my opinion saving of the grid state in database on the server or in the localStorage is better way as the usage of cookie. The best way depends on the project's requirements in which you use it. For example the usage of the database storage on the server allows you to implement roaming state of the grid. If you use the localStorage instead of cookies the user preferences will be lost if the user goes to another computer or just if the user will use another web browser on the same computer.

网格状态的另一个问题是维护.您通常在 JavaScript 或 HTML 文件中而不是在数据库中保存的有关网格列的信息.在这种情况下,两个来源在网格变化上可能不同步.您可以轻松想象更新问题的不同场景.不过在某些场景下,用户偏好的优势太大,劣势小的问题就不那么重要了,解决起来也相对容易.

Another problem with the grid state is the maintenance. The information about the columns of the grid you hold typically in the JavaScript or HTML files and not in the database. In the case the both sources can be not synchronous on the changes in the grid. Different scenarios of the update problem could you easy imagine. Nevertheless the advantages of user's preferences so large in some scenarios that the problems with small disadvantages are not so important and can be solved relatively easy.

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

So I'll spend some time to implement two demos which shows how it can be implemented. I used localStorage in my demos because of many reasons. I mention only two from there:

  1. Cookies 是一种向服务器发送永久不同信息或从服务器发送永久不同信息的方式,但实际上并不需要.它增加了 HTTP 标头的大小并降低了网站的性能(参见 此处 例如).
  2. Cookie 有非常严格的限制.对应于 rfc2109 的 6.3 部分或 6.1 of rfc6265:每个 cookie 至少 4096 字节,每个域至少 50 个 cookie(20 英寸rfc2109),总共至少 3000 个 cookie(rfc2109 中有 300 个).所以cookies不能用来保存太多信息.例如,如果您要保存每个网页的每个网格的状态,则可以快速达到限制.
  1. Cookies is the way which send permanently different information to or from the server which is not really requited. It increases the size of HTTP header and decreases the performance of the web site (see here for example).
  2. Cookies have very hard restrictions. Corresponds to the section 6.3 of rfc2109 or 6.1 of rfc6265: At least 4096 bytes per cookie, at least 50 cookies per domain (20 in rfc2109), at least 3000 cookies total (300 in rfc2109). So the cookies one can't use to save too many information. For example if you would save state of every grid of every your web page you can quickly achieve the limits.

另一方面,所有现代浏览器都支持 localStorage,并且将从 IE8 开始的 Internet Explorer 支持(请参阅 此处).localStorage 将按来源(如 a1.example.com、a2.example.com、a3.example.com 等)自动保存,并且每个来源有 5 MB 的任意限制(请参阅 此处).所以如果你小心使用空间,你将远离任何限制.

On the other side localStorage are supported by all modern browsers and will be supported in Internet Explorer starting with IE8 (see here). The localStorage will be automatically saved per origins (like a1.example.com, a2.example.com, a3.example.com, etc) and has arbitrary limit of 5 MB per origin (see here). So if you use the space carefully you will far from the any limits.

所以我在我的演示中使用了 localStorage.我还应该提到,有一些插件像 jStorage 使用 localStorage 如果它是浏览器支持并使用其他存储,但在旧浏览器(如 IE6/IE7)的情况下为您提供相同的界面.如果您的存储空间较小:128 kB 而不是 5 MB,但最好是 4K,其中有 cookie(请参阅 这里).

So I used in my demos the localStorage. I should additionally mention that there are some plugins like jStorage which use localStorage if it's supported by the browser and use another storage, but the same interface for you in case of old browsers like IE6/IE7. In the case you has only less size of storage: 128 kB instead of 5 MB, but it's better as 4K which one has for cookies (see here).

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

Now about the implementation. I creates two demos: this and it's extended version: this.

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

In the first demo the following states of grid will be saved and automatically restored on the page reload (F5 in the most web browsers):

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

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

In the same way one can extend (or reduce) the list of options which are the part of the saved grid state.

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

The most important parts of the code from the demo you will find below:

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'``)定义为不同页面上的不同值.

Be carefully to define myColumnStateName (the value `'ColumnChooserAndLocalStorage.colState'``) in the demo) to different values on the different pages.

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

The second demo is the extension of the first one using the technique from my old answer to your another question. The demo use the searching toolbar and synchronize additionally information between the advanced searching form and the searching toolbar.

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

UPDATED: The next answer contains extended version of the code included above. It shows how to persist the selected rows (or row) additionally. Another answer shows how to persist the list of expanded nodes of the tree grid and expand the nodes on the relaoding of the page.

这篇关于持久化 jqGrid 列首选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆