ExtJS の DataGrid でページング処理を実装

Ext JS の DataGrid は多機能で便利なのだが、表示するデータ数が増えるとパフォーマンスに影響がでる。クライアント PC の性能やブラウザに依存するだろうが、数百件程度のデータでも結構厳しい印象がある。

そこで、ページ処理を実装して一度に表示するデータを少なくする事を考えてみた。

DataGrid でページング処理を実施するには Ext.PagingToolbar クラスを使用する。

PagingToolbar はページング処理時に、設定された Ext.data.Store オブジェクトに対して以下のようなメソッド呼び出しを内部で処理する。

store.load({params: {start: 開始位置, limit: 件数}});

ただし、Ext.data.Store の load メソッドは Ext.data.DataProxy と Ext.data.DataReader を使って処理するようになっており、サーバーから 1ページ分のデータを取得するような処理を対象としている。(Ext.data.MemoryProxy はページングに未対応)

そのため、JavaScript の変数に格納されたデータにページング処理を適用するには独自の Proxy を定義する必要がある。

<html>
<head>
<link rel="stylesheet" type="text/css" href="ext-2.0.1/resources/css/ext-all.css" />
<script type="text/javascript" src="ext-2.0.1/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext-2.0.1/ext-all.js"></script>
<script type="text/javascript">
<!--
    Ext.BLANK_IMAGE_URL = "ext-2.0.1/resources/images/default/s.gif";

    var grid = null;

    //独自の Proxy 定義
    CustomProxy = function(data){
        CustomProxy.superclass.constructor.call(this);
        this.data = data;
    };

    //MemoryProxy の実装を参考にして、
    //メモリー上のデータに対するページング処理の実装を定義
    Ext.extend(CustomProxy, Ext.data.DataProxy, {
        load : function(params, reader, callback, scope, arg){
            var result;
            try {
                result = reader.readRecords(this.data);
                var tempList = result.records;
                var newList = new Array();

                var start = params.start;
                var end = start + params.limit;

                if (end > tempList.length) {
                    end = tempList.length;
                }

                for (var i = start; i < end; i++) {
                    newList.push(tempList[i]);
                }

                result.records = newList;
            }
            catch(e) {
                this.fireEvent("loadexception", this, arg, null, e);
                callback.call(scope, null, arg, false);
                return;
            }
            callback.call(scope, result, arg, true);
        },
        update : function(params, records){
        }
    });

    Ext.onReady(function() {

        var data = [
            {title: 'test1', point: 1, date: '2008/12/1'},
            {title: 'test2', point: 14.1, date: '2007/12/2'},
            {title: 'test3', point: 12, date: '2007/12/1'},
            ・・・
            {title: 'test12', point: 1.10, date: '2007/12/2'}
        ];

        //データのマッピング情報の定義
        var store = new Ext.data.Store({
            proxy: new CustomProxy(data),
            reader: new Ext.data.JsonReader({
                fields: [
                    {name: 'title'},
                    ・・・
                ]
            })
        });

        grid = new Ext.grid.GridPanel({
            columns: [
                ・・・
            ],
            //DataGrid の下部にページングのツールバーを表示
            bbar: new Ext.PagingToolbar({
                //1ページを 5件に設定
                pageSize: 5,
                displayInfo: true,
                store: store
            }),
            store: store,
            width: 600,
            height: 200
        });

        grid.render('grid-sample');

        //1ページ目のデータを読み込む
        store.load({params:{start:0, limit:5}});
    });
//-->
</script>
</head>
<body>
<div id="grid-sample"></div>
</body>
</html>