Ext JS 2.0 の GridPanel に動的に行追加してみる

どうも jQuery でがんばってUIを構築するのに疲れたので、デブサミで知った Ext JS に浮気してみた。確かにUI構築はかなり楽になるけど、いかんせん日本語の情報が少ない。本家のAPIドキュメントでも肝心の引数がobjectとしか書かれてなくて、いろいろ試行錯誤しないといけない。なので少しずつメモ書きしてみる。

まずはHTMLから。Ext JS は2.0.2を使って、同梱されている jQuery 1.2.3 を利用する。
HTMLではJSファイルを読み込んでいるだけ。 Ext JS はDOMを操作してUIを作るのではなくて、DOMを構築してUIを作るスタイルらしい。今回は div#frameworks に GridPanel をレンダリングする。

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="./js/jquery.js"></script>
<script type="text/javascript" src="./js/ext-jquery-adapter.js"></script>
<script type="text/javascript" src="./js/ext-all.js"></script>
<script type="text/javascript" src="./js/locale/ext-lang-ja.js"></script>
<script type="text/javascript" src="./js/site.js"></script>
<link rel="stylesheet" href="./css/ext-all.css" type="text/css" />
</head>
<body>
    <div id="frameworks" />
    <input id="python" type="button" value="python" />
    <input id="ruby" type="button" value="ruby" />
    <input id="java" type="button" value="Java" />
    <input id="dotnet" type="button" value=".NET" />
</body>
</html>

続いてJavaScript。Ext.grid.GridPanel を使いこなすにはいくつかクラスが必要。

  • Ext.data.Record・・・データ
  • Ext.data.Store・・・データ格納場所。実際は JsonStore とか SimpleStore といったサブクラスを使う方が便利。
    • Ext.data.DataProxy・・・データをどこ(メモリかサーバか)から読み取るかを決定。
    • Ext.data.DataReader・・・データをどうやって(Arrayなのか、Jsonなのか)読み取るかを決定
  • Ext.grid.ColumnModel・・・データをどうやって表示するか

Ext.data.Store を使わずにサブクラスを利用する場合、内部で生成してくれるのでDataProxyとDataReaderはあまり意識しなくていい。今回は SimpleStore を使う。

Ext.data.Record はすこし癖があって、こんな感じに段階を踏んで使用する。

var TopicRecord = Ext.data.Record.create([
    {name: 'title', mapping: 'topic_title'},
    {name: 'author', mapping: 'username'},
    {name: 'totalPosts', mapping: 'topic_replies', type: 'int'},
    {name: 'lastPost', mapping: 'post_time', type: 'date'},
    {name: 'lastPoster', mapping: 'user2'},
    {name: 'excerpt', mapping: 'post_text'}
]);

var myNewRecord = new TopicRecord({
    title: 'Do my job please',
    author: 'noobie',
    totalPosts: 1,
    lastPost: new Date(),
    lastPoster: 'Animal',
    excerpt: 'No way dude!'
});

ただし、これだと面倒なので SimpleStore の生成時に定義してしまう方法もある。今回はこちらを使う。

var ds = new Ext.data.SimpleStore({
    fields: [
        {name: 'title', mapping: 'topic_title'},
        {name: 'author', mapping: 'username'},
        {name: 'totalPosts', mapping: 'topic_replies', type: 'int'},
        {name: 'lastPost', mapping: 'post_time', type: 'date'},
        {name: 'lastPoster', mapping: 'user2'},
        {name: 'excerpt', mapping: 'post_text'}
    ]
});
var myNewRecord = new ds.reader.recordType({
    title: 'Do my job please',
    author: 'noobie',
    totalPosts: 1,
    lastPost: new Date(),
    lastPoster: 'Animal',
    excerpt: 'No way dude!'
}


site.jsのコードはこんな感じ。

Ext.onReady(function() {
    Ext.BLANK_IMAGE_URL = ".images/default/s.gif";

    //Storeの生成
    var ds = new Ext.data.SimpleStore({
        fields: [ //Ext.data.Record定義
            {name: 'name'},
            {name: 'language'},
            {name: 'version'}
        ]
    });

    //GridPanelの生成
    var grid = new Ext.grid.GridPanel({
        store: ds,
        columns: [ //Ext.grid.ColumnModel定義
            {header: 'フレームワーク', width: 0.5, sortable: true, dataIndex: 'name'},
            {header: '言語', width: 0.3, sortable: true, dataIndex: 'language'},
            {header: 'バージョン', width: 0.2, sortable: false, dataIndex: 'version'}
        ],
        viewConfig: { forceFit: true },
        renderTo: 'frameworks',
        disableSelection: true,
        frame: true,
        autoHeight: true
    });

    //イベントハンドラの登録
    Ext.addBehaviors({
        'input#python@click' : function() {
            ds.add(new ds.reader.recordType({ name:'Django', language:'python', version:'0.96.1' }))
        },
        'input#ruby@click' : function() {
            ds.add(new ds.reader.recordType({ name:'Ruby on Rails', language:'ruby', version:'2.0' }))
        },
        'input#java@click' : function() {
            ds.add(new ds.reader.recordType({ name:'SAStruts', language:'Java', version:'1.0' }))
        },
        'input#dotnet@click' : function() {
            ds.add(new ds.reader.recordType({ name:'ASP.NET', language:'.NET', version:'3.5' }))
        }
    });
});

実行するとこんな画面が表示される。

ボタンを押すと行が追加される。いくつか追加した画面はこんな感じ。