Ext JS に関しては,新しい記事は Sunvisor Lab. ExtJS 別館 にあります。そちらもよろしくお願いいたします。
Ext Direct
サーバーサイドをxFrameworkPXにして,画面デザインはExt Designerでやって,サーバーとのデータのやりとりはExt Directで行おうという計画で勉強&実験中です。
まず,スタッフのリストとグループのリストをMySQLに持って,グループを選択するとグリッドにスタッフがリストされるってのをやってみました。
- MySQLにテーブルtbl_staff(スタッフのリスト)とtbl_shozoku(グループのリスト)を作成
- xFramoworkPXのExt Directコントローラーを作成
- xFrameworkPXのモジュールをそれぞれのテーブル用に作成
- Designerで画面をデザインして,Ext Directでデータのやりとり
というようなイメージで始めましたが,いくつも,つまづきました。
TreePanelに所属ツリーを表示
これはわりと簡単にいきました。tbl_shozokuは,回層状になったグループが格納されていて,上位の所属をupper_idというフィールドが持っています。
<?php /** * 所属モジュール * 所属マスタ * @author sunvisor * */ class shozoku extends xFrameworkPX_Model { public $usetable = 'tbl_shozoku'; /** * ツリーを得る * TreeLoaderから呼び出される * @param unknown_type $id */ public function getTree($id) { $sql = "SELECT id, shozoku_nm text FROM " . $this->getTableName(); if( $id === 'root') { $cond = 'upper_id = 0'; } else { $cond = 'upper_id = ' . $id; }; return $this->rowAll( array( 'query' => $sql, 'where' => $cond ) ); } }
こんな感じでモジュールを作りました。Javascript側は非常に簡単で,TreeLoaderのdirectFnに Shozoku.getTreeと指定しただけで思ったような動作(折りたたまれているノードを開くと下位の所属が表示される)を実現できました。
グリッドにスタッフを表示
まずは全員を表示ということで
public function getAllData() { $ret = array(); $items = $this->get( 'all', array( 'fields' => array( 'id', 'staff_no', 'name_kanji', 'name_kana', 'shikaku_ryk', 'hairetsu' ) ) ); $ret['total'] = count($items); $ret['data'] = $items; return $items; }
サーバー側のコントローラーは上記のように作りまして,今度はDirectStoreのdirectFnにStaff.getAddDataをセット。
ところが最初なかなかうまくいきませんでした。ほんとに長いことハマったのですが,
Ext.Direct.addProvider(Ext.app.REMOTING_API);
Ext Directにプロバイダを追加する上記の1行の場所が問題でした。最初僕は,index.jsのExt.Readyの中で呼び出していましたが,それではだめだったんです。ストアのクラスがnewされる前に呼び出さなければならなかったのです。Designerで生成される,ソースでは,ストアのクラスのファイルの中でnewされます。htmlの中でこのクラスファイルを読む前に実行しなければならないので,僕の場合は,Viewportのクラスファイルの先頭で実行するようにしたら動作しました。
パラメータを渡す
次に,ツリーが選択されたら所属するスタッフが表示されるというのを実装します。
最初,getData($shozoku)というようなメソッドをモジュールに作って,それを呼び出せばいいと思いました。が,DirectStoreのdirectFnに関数名をセットして,パラメータに関するいくつかのconfigを書き換えてみても,パラメータがサーバー側に渡りませんでした。いまでも渡し方がわかりません。
わかりました。基本的には,paramOrderにパラメータ名をセットして,loadメソッドに引数を渡してやればできました。そうやっていたつもりなのですが,なぜだかうまく動かなかったみたいです。落ち着いて実験したら成功しました。
StaffStore = Ext.extend(Ext.data.DirectStore, { constructor: function(cfg) { cfg = cfg || {}; StaffStore.superclass.constructor.call(this, Ext.apply({ storeId: 'StaffStore', directFn: staff.getData, paramsAsHash: false, paramOrder: 'id', : : : }, cfg)); } });
Storeに上記のように,paramOrderをセットして,paramsAsHashをfalseに設定します。
onTpShozokuClick: function (node, e){ Ext.StoreMgr.get('StaffStore').load({ params: { id: node.id } }); },
呼び出す方は,loadメソッドに上記のようにparamsコンフィグにパラメータをセットして渡します。