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プロバイダが追加されてなければならないのに,それが処理されていないのでエラーになります。
