Ext JS に関しては,新しい記事は Sunvisor Lab. ExtJS 別館 にあります。そちらもよろしくお願いいたします。
07.DirectStore を xFrameworkPX とともに使う
DirectStore/EditorGridPanel を使ってアプリケーションを作る時の基本的なことを書き留めておきたいと思います。サーバーサイドは,xFrameworkPX を使います。
サーバーサイド
xFrameworkPXでは,ExtDirect コントローラーとモジュールをつくります。通常の xFrameworkPX の使い方については,ドキュメントに詳しいので,ここでは ExtDirect に関することだけを書きます。
コントローラー
ファイル名:webapp/.extdirect.php
<?php class extdirect extends xFrameworkPX_Controller_ExtDirect { public $direct = array( 'namespace' => 'Ext.myApp' ); public $modules = array( 'testdata' => array( 'conn' => 'default' ) ); }
xFrameworkPX_Controller_ExtDirect を継承したクラスを作ります。このクラスの execute メソッドでは,ExtDirect の API を返します。
4行目で$direct 配列にオプションを設定しています。ここでは namespace に Ext.myApp と設定しています。namespace に何も設定しない場合,サーバーサイドのメソッドは モジュール名.メソッド名 の形式になりますが,namespace を設定すると namespace.モジュール名.メソッド名 の形式になります。個人的には namespace を設定したほうがソースが読みやすくなると思います。
$direct で設定できる他のオプションは次の通りです。
オプション | 初期値 | 備考 |
---|---|---|
url | extdirect.html | APIのURL。これを変える時は,コントローラーのクラス名とファイル名も一致させる必要があると思います。(きっと) |
type | remoting | |
descriptor | Ext.app.REMOTING_API | |
namespace | (設定なし) |
モジュール
<?php class testdata extends xFrameworkPX_Model { var $usetable = 'tblData'; public function getStore() { $result = $this->get( 'all', array( 'fields' => array( 'id','val1','val2','val3','val4','val5','val6','val7', 'val8','val9','val10','val11','val12','val13' ) ) ); return array( 'success' => true, 'data' => $result, 'total' => count($result) ); } }
テストデータのテーブルですので,DBのテーブルを読んできて,それを全部返しています。本当は抽出条件などを指定するところですが,まぁサンプルということで。最後に取得したデータを連想配列にセットしてます。これはDirectStoreの形式に合わせています。
クライアントサイド
Ext.Designerで,StoreとUI部分を作ります。出力されたコードは次のような感じ。
ストア
ファイル名:MyStore.js
MyStore = Ext.extend(Ext.data.DirectStore, { constructor: function(cfg) { cfg = cfg || {}; MyStore.superclass.constructor.call(this, Ext.apply({ storeId: 'MyStore', directFn: Ext.myApp.testdata.getStore, root: 'data', fields: [ { name: 'id', mapping: 'id', type: 'int' }, { name: 'val1', mapping: 'val1', type: 'int' }, : : { name: 'val13', mapping: 'val13', type: 'int' } ] }, cfg)); } }); new MyStore();
directFn のところに namespace.モジュール名.メソッド名 で先程作ったメソッドを設定(Ext.myApp.testdata.getStore)します。root コンフィグには,モジュールでデータをセットした配列のキー(data)をセットします。
UI部分
ファイル名:MyViewport.ui.js
MyViewportUi = Ext.extend(Ext.Viewport, { layout: 'border', initComponent: function() { this.items = [ { xtype: 'editorgrid', title: 'My Grid', store: 'MyStore', region: 'center', height: 410, ref: 'grdData', columns: [ { xtype: 'gridcolumn', header: 'id', dataIndex: 'id', sortable: true, width: 100, editor: { xtype: 'textfield' } }, { xtype: 'gridcolumn', header: 'val1', dataIndex: 'val1', sortable: true, width: 100, editor: { xtype: 'textfield' } }, : : { xtype: 'gridcolumn', header: 'val13', dataIndex: 'val13', sortable: true, width: 100, editor: { xtype: 'textfield' } } ] } ]; MyViewportUi.superclass.initComponent.call(this); } });
自動生成されたままです。というか Designer で出力された ui.js のファイルは触らないのが約束です。
ファイル名:MyViewport.js
Ext.Direct.addProvider(Ext.app.REMOTING_API); MyViewport = Ext.extend(MyViewportUi, { initComponent: function() { MyViewport.superclass.initComponent.call(this); this.on('beforerender', this.onBeforeRender, this); }, onBeforeRender: function () { var s = this.grdData.getStore(); s.load(); } }
このファイルは触っても大丈夫です。ここにイベントハンドラなどを書きます。ViewPort の beforerender イベントで,Storeのload()メソッドをコールしています。
起動部分
ファイル名:index.js
Ext.onReady(function() { Ext.QuickTips.init(); var cmp1 = new MyViewport({ renderTo: Ext.getBody() }); cmp1.show(); });
index.js に Ext.onReady を書きます。
ファイル名:index.html
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>project.xds</title> <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css"/> </head> <body> <script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script> <script type="text/javascript" src="extjs/ext-all-debug.js"></script> <!-- Ext Direct API --> <script type="text/javascript" src="extdirect.html"></script> <!-- /Ext Direct API --> <script type="text/javascript" src="js/MyViewport.ui.js"></script> <script type="text/javascript" src="js/MyViewport.js"></script> <script type="text/javascript" src="js/MyStore.js"></script> <script type="text/javascript" src="js/index.js"></script> </body> </html>
uiコンポーネントを読み込む前に Ext.Direct API を読み込んでいます。
MyViewport.js の1行目に Ext.Direct.addProvider(Ext.app.REMOTING_API); を記述しています。この行の記述場所を間違うとStoreの作成に失敗してしまいます。
失敗例:Ext.onReadyの中でコールする。
index.jsの前にMyStore.jsを読み込んでいます。Designerの出力するコードでは,MyStore.jsの最後で,Storeがnewされています。その時点でExt.Directプロバイダが追加されてなければならないのに,それが処理されていないのでエラーになります。