プログラミングノート

一からものを作ることが好きなエンジニアの開発ブログです。

Ext.dataのProxy, Reader, Storeについて

GridPanel、ComboBox、DataViewなどのコンポーネントから利用されるProxy、Reader、Storeの各クラスですが、生成方法が色々あって分かりづらかったのでまとめてみました。


まず、StoreはView(Grid)からのリクエストに応じて内部の情報を操作するクラスで、基本的に下記のような構造で生成します。

var store = new Ext.data.Store({
  proxy: new Ext.data.XXXProxy({
    ...  
  }),
  reader: new Ext.data.XXXReader({
    ...
  })
});


Store内部で生成しているProxyはデータを取得するクラス、Readerはそのデータを内部形式(Ext.data.Record)にマッピングするクラスです。


Ext.dataパッケージにはProxy、Reader、Storeに関連するクラスが複数存在しているので、用途に応じた使い分けが必要です。


Proxy

  • Ext.data.DataProxy (Extends: Observable)

ベースクラス(抽象クラス)

  • Ext.data.MemoryProxy (Extends: DataProxy)

メモリ(変数)からデータを取得する際に利用

  • Ext.data.HttpProxy (Extends: DataProxy)

HTTP経由でデータを取得する際に利用

  • Ext.data.ScriptTagProxy (Extends: DataProxy)

JSONP形式で提供されているデータを取得する際に利用

Reader

  • Ext.data.DataReader (Extends: Object)

ベースクラス(抽象クラス)

  • Ext.data.XmlReader (Extends: DataReader)

XMLからExt.data.Recordへのマッピング

  • Ext.data.JsonReader (Extends: DataReader)

JSONからExt.data.Recordへのマッピング

  • Ext.data.ArrayReader (Extends: JsonReader)

Array(配列)からExt.data.Recordへのマッピング

Store

  • Ext.data.Store (Extends: Observable)

ベースクラス

  • Ext.data.SimpleStore (Extends: Store)

ArrayからStoreを生成するヘルパークラス

  • Ext.data.JsonStore (Extends: Store)

JSONからStoreを生成するヘルパークラス

  • Ext.data.GroupingStore (Extends: Store)

グルーピングレコードを実装するStoreを生成するクラス


以下Array、JSONXMLからGridを生成するサンプルです。

ArrayからStore生成

Ext.data.MemoryProxyに直接Arrayを指定してデータを生成し、Ext.data.ArrayReaderで各配列の要素にマッピングします。ここで指定したnameプロパティは後ほどGridを生成する際に利用します。

var store = new Ext.data.Store({
  proxy: new Ext.data.MemoryProxy([
    [1, 'Bill', 'Gardener'], 
    [2, 'Ben', 'Horticulturalist'], 
    [3, 'Mark', 'Programer'] 
  ]),
  reader: new Ext.data.ArrayReader({}, [
    {name: 'id'},
    {name: 'name'},
    {name: 'occupation'}
  ])
});
store.load();


また、MemoryProxyとArrayReader組み込み済みのExt.data.SimpleStoreを利用すれば手軽に生成できます。

var store = new Ext.data.SimpleStore({
  data: [
    [1, 'Bill', 'Gardener'], 
    [2, 'Ben', 'Horticulturalist'], 
    [3, 'Mark', 'Programer'] 
  ],
  fields: [
    {name: 'id'},
    {name: 'name'},
    {name: 'occupation'}
  ]
});

JSONからStore生成

Arrayと同じ内容のStoreをJSONから生成します。通信して取得するのでExt.data.HttpProxyを指定し、Ext.data.JsonReaderでマッピングの設定を行います。

var store = new Ext.data.Store({
  proxy: new Ext.data.HttpProxy({
    url: 'get-json.php'
  }),
  reader: new Ext.data.JsonReader({
    root: 'rows',             //各データを保持しているキー
    totalProperty: 'results'  //データ数を保持しているキー
  },[
    {name: 'id'},
    {name: 'name'},
    {name: 'occupation'}
  ])
});
store.load();


JSONの場合もExt.data.JsonStoreを利用すれば手軽に利用可能です。JsonStoreはHttpProxyとJsonReaderが組み込み済みなので下記のように両方まとめて指定できます。

var store = new Ext.data.JsonStore({
  url: 'get-json.php',
  root: 'rows',
  totalProperty: 'results',
  fields: [
    {name: 'id'},
    {name: 'name'},
    {name: 'occupation'}
  ]
});  
store.load();  


get-json.phpは固定のJSONを出力しています。

<?php
echo <<<E
{
  'results': 3,
  'rows': [
    {'id': 1, 'name': 'Bill', occupation: 'Gardener'},
    {'id': 2, 'name': 'Ben' , occupation: 'Horticulturalist'},
    {'id': 3, 'name': 'Mark' , occupation: 'Programer'}
  ]
}
E;

XMLからStore生成

Arrayと同じ内容のStoreを今度はXMLから生成します。内容はJSONとほぼ同じなので省略。

var store = new Ext.data.Store({
  proxy: new Ext.data.HttpProxy({
     url: 'get-xml.php'
  }),
  reader:new Ext.data.XmlReader({
     record: 'row',
     totalRecords: 'results'
  }, [
     {name: 'id'},
     {name: 'name'},
     {name: 'occupation'}
  ])
});
store.load();


get-xml.phpは固定のXMLを出力しています。

<?php
header('Content-type: text/xml;');
echo <<<E
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
  <results>3</results>
  <row>
    <id>1</id>
    <name>Bill</name>
    <occupation>Gardener</occupation>
  </row>
  <row>
    <id>2</id>
    <name>Ben</name>
    <occupation>Horticulturalist</occupation>
  </row>
  <row>
    <id>3</id>
    <name>Mark</name>
    <occupation>Programer</occupation>
  </row>
</dataset>  
E;

Gridで利用する

最後に上記で生成したStoreを利用してGridを生成する方法です。Gridを生成するにはStoreのデータをどのように表示するかをExt.grid.ColumnModelで指定します。headerがGridに表示される列のヘッダ名称、dataIndexがReaderでマッピングしたnameプロパティです。

var cm = new Ext.grid.ColumnModel([{
    header: 'ID',
    dataIndex: 'id',
    width: 50
  },{
    header: 'Name',
    dataIndex: 'name',
    width: 100
  },{
    header: 'Occupation',
    dataIndex: 'occupation',
    width: 100
}]);

var grid = new Ext.grid.GridPanel({
    title: 'Sample',
    collapsible: true,
    frame: true,
    width: 300,
    height: 200,
    store: store,
    cm: cm,
    renderTo: Ext.getBody()
});

//Ext.data.Recordオブジェクトを取得
grid.on('rowdblclick', function(grid, rowIndex, e){
    var record = grid.getStore().getAt(rowIndex);
    console.log(record);
});

単純にGridに表示するために必要な情報はこんなところでしょうか。