Store の内容を永続化する方法

「サンプルはコンポーネントばかりだから、裏方はどうすりゃいいのか悩むよね?」
Ext JS には、MS-Excel 風にグリッド上でそのまま編集できる EditorGridPanel が用意されている。Web アプリとは思えない UI を作ることができる便利なモノだ。しかし、編集した内容をサーバーに送るにはどうするばいいのだろうか? が、今回のサンプル。

方法は何通りもあるけれど、EditorGridPanel での変更が自動的に Store に保存されるので、JsonStore の update イベントを拾って、変更部分だけをサーバーに送る方法にしてみた。

new Ext.data.JsonStore({
     url: '/READ',
     root: 'recs',
     fields: ['f1', 'f2'],
     listeners: {
          update: function(store, rec, opt) {
               // 変更されたデータを取得
               var data = rec.getChanges();

               // サーバーへ送信
               Ext.Ajax.request({
                    method: 'POST',
                    url: '/UPDATE',
                    params: data
               });
          }
     }
});

変更部分だけぢゃなく、レコードの内容をすべてサーバーに送りたければ、"rec.getChanges();" を "rec.data;" に置き換えればいい。data は Ext.data.Record のパブリックプロパティで、レコードの内容を表すオブジェクトになっている。

ところで…。EditorGridPanel の中身を変更すると、左上に赤い三角印が付くが、これは、そのセルが変更されたことを表している。なので、上記の処理でサーバーへデータを送れば、三角印は消えて欲しいところだ。

Ext.data.Record には、変更されたことを表す dirty フラグ (読取専用のパブリックプロパティ) があり、三角印はこれと連動しているのだが、dirty フラグをオフにするメソッドがリファレンスには見当たらない。実は、commit してやれば、dirty フラグはオフになるのだが、commit を呼ぶと、もう一度 update イベントが発生し、"無限ループのできあがり!" となる。で、そこをうまく回避するところまで書くと、こんな感じになる。

new Ext.data.JsonStore({
     url: '/READ',
     root: 'recs',
     fields: ['f1', 'f2'],
     listeners: {
          update: function(store, rec, opt) {
               // 変更箇所がなければ終了
               if (!rec.dirty) return;

               // 変更されたデータを取得
               var data = rec.getChanges();

               // サーバーへ送信
               Ext.Ajax.request({
                    method: 'POST',
                    url: '/UPDATE',
                    params: data,
                    listeners: {success: function(res, opt) {rec.commit();}}
               });
          }
     }
});

3.0 には Store に batchSave が用意されてるので、たぶん、こんなことはしなくてもいいはず。

※ これらのソースは実際のアプリから抜いたコードをブログ用に加工したもので、動作検証は不十分です。もし、これを参考にして動かないようであれば、ご一報ください。m(__)m