web-dev-qa-db-ja.com

jqGrid列設定の永続化

ASP.NET MVC 3アプリケーションには、いくつかの列を持つjqGridがいくつかあります。一部の列をデフォルトで非表示にするために、列定義に以下を追加しました。

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},

これで、列を適切に表示/非表示にできます。では、この情報をどのように保持しますか? DB?クッキーとして?他の方法?データ自体に関連するものではなく、実際にはユーザーの好みであるこの種の情報を保存するための好ましい方法はありますか?


詳細

以下のオレグのコメントに基づいて、もう少し情報を提供したいと思います。

ここでのポイントは、ユーザーの好みに基づいて表示できる10〜15列のグリッドがあることです。簡単な例として、私のグリッドの1つに次の9つの列があります。

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

ユーザーは、個人的な好みに基づいて、これらの9つの列のいずれかを非表示/表示できます。

私がやりたいのは、特定のユーザーが表示したい列を永続化する方法を提供することです。これにより、そのグリッドのあるページが表示されるたびに、表示する列を再選択する必要がなくなります。

27
itsmatt

あなたの質問はとても興味深いと思いました。グリッドのユーザー状態を保存することに関する質問は、多くの場合興味深いものです。 cookieを使用するこのような問題にはいくつかの興味深い答えがあります(たとえば、 ここ を参照)。

私の意見では、サーバー上のデータベースまたはlocalStorageにグリッド状態を保存することは、Cookieの使用法としてより良い方法です。最善の方法は、それを使用するプロジェクトの要件によって異なります。たとえば、サーバー上のデータベースストレージを使用すると、グリッドのローミング状態を実装できます。 Cookieの代わりにlocalStorageを使用すると、ユーザーが別のコンピューターに移動した場合、またはユーザーが同じコンピューターで別のWebブラウザーを使用した場合に、ユーザー設定が失われます。

グリッド状態のもう1つの問題は、メンテナンスです。通常、データベースではなくJavaScriptまたはHTMLファイルに保持するグリッドの列に関する情報。両方のソースがグリッドの変更で同期できない場合。更新の問題のさまざまなシナリオを簡単に想像できます。それにもかかわらず、一部のシナリオではユーザーの好みの利点が非常に大きいため、小さな欠点の問題はそれほど重要ではなく、比較的簡単に解決できます。

そこで、実装方法を示す2つのデモを実装するために少し時間を費やします。多くの理由から、デモではlocalStorageを使用しました。私はそこから2つだけ言及します:

  1. Cookieは、実際には必要とされないサーバーとの間で永続的に異なる情報を送信する方法です。 HTTPヘッダーのサイズが大きくなり、Webサイトのパフォーマンスが低下します(たとえば、 ここ を参照)。
  2. クッキーには非常に厳しい制限があります。 rfc2109のセクション 6. またはrfc6265の 6.1 に対応:Cookieあたり少なくとも4096バイト、ドメインあたり少なくとも50 Cookie(rfc2109では20)、合計で少なくとも3000 Cookie (rfc2109では300)。したがって、あまりにも多くの情報を保存するために使用できないCookie。たとえば、すべてのWebページのすべてのグリッドの状態を保存する場合、制限をすばやく達成できます。

一方、localStorageはすべての最新のブラウザーでサポートされており、IE8以降のInternet Explorerでサポートされます( ここ を参照)。 localStorageは、オリジン(a1.example.com、a2.example.com、a3.example.comなど)ごとに自動的に保存され、オリジンごとに5 MBの任意の制限があります( を参照)ここ )。したがって、スペースを慎重に使用すると、制限から遠く離れます。

そのため、デモではlocalStorageを使用しました。 jStorage のようなプラグインがあり、ブラウザでサポートされていて別のストレージを使用している場合はlocalStorageを使用しますが、IE6などの古いブラウザの場合は同じインターフェイスを使用します。/IE7。ストレージのサイズが少ない場合:5MBではなく128kBですが、Cookie用の4Kよりも優れています( ここ を参照)。

次に、実装について説明します。私は2つのデモを作成します: this そしてそれは拡張バージョンです: this

最初の デモでは、グリッドの次の状態が保存され、ページのリロード時に自動的に復元されます(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);
    }
});

myColumnStateName(デモでは値 `'ColumnChooserAndLocalStorage.colState'``)を異なるページの異なる値に定義するように注意してください。

2番目のデモ は、私の 古い回答 から別の質問へのテクニックを使用した最初のデモの拡張です。デモでは検索ツールバーを使用し、高度な検索フォームと検索ツールバーの間で追加情報を同期します。

[〜#〜]更新された[〜#〜]次の回答 には、上記のコードの拡張バージョンが含まれています。選択した行(または行)を追加で永続化する方法を示します。 別の回答 は、ツリーグリッドの展開されたノードのリストを永続化し、ページのリロードでノードを展開する方法を示しています。

41
Oleg