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' })) } }); });