メイン



ColumnModel アーカイブ

2008年04月28日

Ext.grid.GridPanelの使い方

まず、ExtJS javascriptライブラリをダウンロードページより、アーカイブ(Ext JS 2.1 SDK)をダウンロードして解凍してください。20080428時点のバージョンは ext-2.1 です。解凍したら、以下のパスのファイルを開いて見ましょう。gridのサンプルはココからも見れます。
【パス】
ext-2.1\examples\grid\array-grid.html
このウィジェットがgridと呼ばれるものです。エクセルのような罫線で表現されたウィジェットで、
  • ソート
  • 各セルの編集
  • グルーピング
  • サマリ
  • フィルタ
simplegrid.PNG なんかも出来ます。すごいですね。今日はこのgridの基本的な実装を解説してみたいと思います。あと、いきなりgirdとか言われても・・と言う方にはここにExtJSのチュートリアルを簡単にまとめてみました。
まず、以下に今回解説するgridのソースを全て載せてみましたので、この実装方法とコンフィグを解説します。

動作サンプルとサンプルソース
Ext.onReady( function(){
    var store = new Ext.data.SimpleStore({
        fields: [
            { name: 'a' },
            { name: 'b' }
        ],
        data:[ 
            [ 'hoge', 1 ],
            [ 'moge', 2 ],
            [ 'fuga', 3 ] 
        ]
    });

    var clmnModel = new Ext.grid.ColumnModel([
        { header: "title", width: 200, dataIndex: 'a' },
        { header: "number", width: 100, sortable: true, dataIndex: 'b' }
    ]);
 
    var grid = new Ext.grid.GridPanel({
        store:store,
        colModel:clmnModel,
        renderTo:'renderTarget',
        title:'simple-grid',
        stripeRows:true,
        height:150,
        width:316,
        frame:true
    });
});

【Ext.grid.GridPanelの解説】

それではgirdを見ていきたいと思います。
    var grid = new Ext.grid.GridPanel({
という箇所がグリッドそのものになります。この定義の仕方は、これからたくさん出てくるので先に解説してしまいます。
Ext.grid.GridPanel({});の{}定義体はオブジェクトリテラルと呼ばれるもので、ExtJSではこの書式で実装していくことがほとんどです。使ってみればそんなに難しいものでは無く、
オブジェクトリテラルとは
  • 中カッコ{}で囲まれて、
  • カンマ,を使ってプロパティが区切られて定義されるもの
だと理解すればいいのではないかと思います。多分乱暴に色々切り捨てた言い方をしたのかもしれませんが、ワタシはそう理解しています。
そしてこのオブジェクトリテラルのプロパティ1つ1つを、ExtJSではコンフィグオプションと呼んでいます。
Ext.grid.GridPanel({ /* コンフィグオプション群 */ })
このコンフィグオプションによって、いろんな表示設定や、機能設定が出来るようになっています。
サンプルソースのgridのコンフィグオプションを上から見ていくと、
store / colModel / renderTo / title / stripeRows / height / width / frame とありまして、このほかにも様々なコンフィグオプションがありますが、GridPanelで必須とされるのは store と colModel になります。ただ、renderToで表示先を指定してあげないと、このサンプルソースではgridが表示されませんので、このstore / colModel / renderTo以外をコメントアウトしたりしてどんなコンフィグなのか試してみるといいかもしれません。

それではこのコンフィグを解説していきたいと思います。
storeは、APIDocumentに
store : Ext.data.Store
The Ext.data.Store the grid should use as its data source (required). 
とあり、storeはデータソースであることがわかります。データの実体ですね。その型はExt.data.Storeを使っているよーと言うことです。

colModelは、
colModel : Object
The Ext.grid.ColumnModel to use when rendering the grid (required). 
とあり、girdの列定義をあらわしています。
ちなみにcolModelは、cmというコンフィグオプション名でもよくて、cmは、colModelを表すshorthand(ショートハンド(エイリアス?))だとAPIDocにあります。どちらでもいいですが、colModel / cm は必須コンフィグです。

renderToは、
    renderTo:'renderTarget',
先にも記述したとおり、表示先を指定するコンフィグです。document.bodyとか、DOMノードのidを表示先に設定してあげます。サンプルソースのように、コンフィグオプションでレンダリング先を指定してあげることも出来ますし、出来上がったgridから以下のようにしてメソッドとして呼び出すことも出来ます。(メソッド名とコンフィグオプションは必ずしも一致しませんし、コンフィグオプションが全てメソッドとして利用できるわけではなさそうです。)
    var grid = new Ext.grid.GridPanel({ /* config options */ });
    grid.render( 'renderTarget' );
サンプルソースで使ったコンフィグの残りは表示レイアウトのオプションになります。
    title:'simple-grid',
    stripeRows:true,
    height:150,
    width:316,
    frame:true
titleはgirdのタイトルになります。これを設定しないとタイトルバーごと表示されません。何かを設定すれば、(例えば空文字でも)タイトルバーは残ります。
stripeRowsは、行を縞々に表示するコンフィグです。ちょっと色が薄いので判りにくいですが、これをtrueにすると行が縞々に表示されます。stripeRowsコンフィグを使わないで実装した場合、デフォルト値がfalseですので、縞々にはなりません。
height / widthはそのまま、縦・横の幅を表します。
最後のframeはこのgridの枠です。true / false で表示・非表示を表していて、デフォルトはfalseです。
コンフィグオプションをつけたり消したりして、表示を見て試してみれば判りやすいかと思います。

【Ext.data.SimpleStoreの解説】

では、GridPanelに必須コンフィグのstoreの解説です。
    var store = new Ext.data.SimpleStore({
        fields: [
            { name: 'a' },
            { name: 'b' }
        ],
        data:[ 
            [ 'hoge', 1 ],
            [ 'moge', 2 ],
            [ 'fuga', 3 ] 
        ]
    });
ソースは上記のようになっています。gridと同じようにExt.data.SimpleStore({ /* コンフィグオプション群 */ })コンフィグオプションを設定します。Ext.data.SimpleStoreはExt.data.Storeを継承したデータストアで、配列でStoreデータを簡単に構築できるクラスです。見ると、fieldsもdataも配列で構築されていることがわかります。
    fields: [
        { name: 'a' },
        { name: 'b' }
    ],
fieldsは、ストア上のフィールド定義です。名前に a / b と付けてみました。gridそのものを見ると列ヘッダにtitle / numberとありますが、ストア上にあるフィールド名は a / b となります。(girdはStoreとColumnModelのファサード(ラッパー)だと理解すればいいと思います。)データを正しくマッピングできるように重複しない名前を定義してあげてください。(マッピングは次のExt.grid.ColumnModelで行います。)
    data:[ 
        [ 'hoge', 1 ],
        [ 'moge', 2 ],
        [ 'fuga', 3 ] 
    ]
dataは、そのまんまデータを表していて、多次元配列(2次元配列)で定義します。表のイメージを実装してあげることが出来るので便利ですが、多次元配列で定義することに注意してください。例えば、fieldsが1つの場合でも
    data:[ 
        'hoge', 
        'moge', 
        'fuga' 
    ]
とせずに
    data:[ 
        [ 'hoge' ], 
        [ 'moge' ], 
        [ 'fuga' ] 
    ]
のように多次元配列で構築する必要があります。

【Ext.grid.ColumnModelの解説】

    var clmnModel = new Ext.grid.ColumnModel([
        { header: "title", width: 200, dataIndex: 'a' },
        { header: "number", width: 100, sortable: true, dataIndex: 'b' }
    ]);
まず、ソースを抜き出してみました。このクラスは
Ext.grid.ColumnModel([{ /* コンフィグオプション群 */ },{ /* コンフィグオプション群 */ } ]);
のように、配列でコンフィグオプションをイニシャライズする必要があります。カラム定義が1つの場合は、コンフィグオプション群も1つになるかと思いますが、以下のように配列で定義しないで実装すると正しく表示されません。(gridの中身が表示されなくなります)
    // 正しく表示されない
    Ext.grid.ColumnModel({ /* コンフィグオプション群 */ });

    // 正しく表示される
    Ext.grid.ColumnModel([ { /* コンフィグオプション群 */ } ]);
コンフィグオプションの中身はその機能や、表示系のオプションがたくさん用意されていて、今回使ってみた機能はsortableというコンフィグです。読んで字のごとく該当列がソートできるか出来ないかを表すコンフィグです。デフォルト(sortableを実装していない場合)はソートできないので、titleフィールドはソート表示がグレーアウトされていて、numberフィールドはソードが出来るようになっています。
    { header: "title", width: 200, dataIndex: 'a' },
    { header: "number", width: 100, sortable: true, dataIndex: 'b' }
headerは列のタイトルとなるコンフィグで、widthは列の幅を表しています。dataIndexは上述のstoreで定義したnameとマッピングしています。必須ではありませんので定義しなくても表示されますが、明示的にマッピングして表示してあげたほうがいいかと思います。
他にもこのサンプルソースにすぐ使えそうな機能コンフィグとして以下のようなものがあります。editorというコンフィグで各セルの編集が出来るようになるのですが、これはgirdそのものがExt.grid.EditorGridPanelでないと機能しないようです。(次回解説します。)
  • hidden:Boolean
    • 列そのものを表示させるかどうかです。trueにすると非表示となります。カラムメニューから再表示させることが出来ます。
  • hideable:Boolean
    • 列を非表示に出来るかどうかです。falseにすると非表示にすることが出来なくなり、カラムメニューから該当列の表示・非表示のチェックボックスが消えます。
  • resizable:Boolean
    • 列の幅をリサイズできるかどうかです。falseにすると、リサイズが出来なくなります。
  • menuDisabled:Boolean
    • 列メニューを使えるようにするかどうかです。trueにすると、該当列の列メニュードロップダウン表示(▼←こんなの)がなくなりメニューが使えなくなります。
  • tooltip:String
    • 列にマウスをあわせたときにtooltipが表示されます。
というわけで、gridの解説をしてみました。ワタシの理解を多分に含めておりますので、誤った情報である可能性がありますのでご注意ください。

[ スポンサードリンク ]

2008年06月23日

Ext.grid.EditorGridPanelの使い方

editorgridsumple.PNG ExtJSのエントリはこちらにまとめてあります

ダウンロードページより、アーカイブ(Ext JS 2.1 SDK)をダウンロードして解凍してください。20080623時点のバージョンは ext-2.1 です。
今日は、ExtJSのEditor Grid Exampleを解説してみたいと思います。
ワタシが作ってみたEditorGridは、上記リンクのサンプルのようにプルダウンやチェックボックスは装備しておりません。EditorGridそのものは非常にシンプルに作った代わりに、編集されたセルを検出するボタンを追加してみました。Gridをフォームとしてどこかへポストしたいといった時に、有効かもしれません。あと、いきなりEditorGridPanelとか言われても・・と言う方にはここにExtJSのチュートリアルを簡単にまとめてみました。
まず、以下に今回解説するEditorGridPanelのソースを全て載せてみましたので、この実装方法とコンフィグを解説します。
動作サンプルとサンプルソース
Ext.onReady( function(){
    var id = 0;
    var reader = new Ext.data.ArrayReader( { id: 0 }, [
          { name: 'str', mapping: 1 },
       { name: 'num', mapping: 2 }
    ]);
    var store = new Ext.data.Store({
        reader: reader,
        data:[ 
            [ id++, 'hoge', 1 ],
            [ id++, 'moge', 2 ],
            [ id++, 'fuga', 3 ]
        ]
    });
    
    var clmnModel = new Ext.grid.ColumnModel([
        { header: "Title", width: 200, sortable: true, dataIndex: 'str', editor: new Ext.form.TextField() },
        { header: "Number", width: 100, sortable: true, dataIndex: 'num', editor: new Ext.form.NumberField() }
    ]);

    var grid = new Ext.grid.EditorGridPanel({
        store:store,
        colModel:clmnModel,
        renderTo:'renderTarget',
        title:'simple-editorgrid',
        stripeRows:true,
        height:200,
        width:320,
        frame:true,
        clicksToEdit:1,
        tbar:[
        { text: 'touch', handler:function(){
            grid.getStore().each( function( targetObj ){
                var touchField = targetObj.getChanges();
                for( name in touchField ){
                    alert(
                        "index : [ " + targetObj.id + " ]\n" + 
                        "fieldName : [ " + name + " ]\n" +
                        "value : [ " + touchField[ name ] +" ]\n" 
                    );
                }
                targetObj.commit();
            });
        }}]
    });
});

【Ext.grid.EditorGridPanelの解説】

それではEditorGridPanelを見ていきたいと思います。普通のGridPanelの使い方はこちらを参照ください。

EditorGridPanel

    var grid = new Ext.grid.EditorGridPanel({
という箇所がエディターグリッドパネルそのものになります。GridPanelと違うところはコンフィグオプションの
     clicksToEdit:1,
という個所と、カラムモデルにeditorというコンフィグオプションを適用しているところだけです。
clicksToEditのAPIDocをみると
The number of clicks on a cell required to display the cell's editor (defaults to 2)
とありまして、セルが編集可能になるクリック数みたいなことが書いてありますが、なんかあんまり関係ないような気がします。(値がいくつでもダブルクリックで編集可能になった)このコンフィグオプションがなくても編集可能になりました。
で、実際に編集可能にするためにはカラムモデルにeditorという設定をしなければならないようです。
    var clmnModel = new Ext.grid.ColumnModel([{ 
        header: "title", 
        width: 200, 
        dataIndex: 'str', 
        editor: new Ext.form.TextField()  // <-コレ
    },
ここのeditorにformパッケージのクラスでnewしてあげると、編集時にそのクラスで動くようになります。例えばComboBoxでnewしてあげるとプルダウンできるようになります。(適宜ComboBoxのコンフィグは必要になります)
これでEditorGridPanelが完成しました。

編集セルの特定

冒頭で記述しましたようにEditorGridの編集個所が特定できないと、どこかのページに値をポストしようにも出来ませんので、この解説をしたいと思います。ポストの前にとりあえず、gridのデータをどこかに渡すためには、
  1. どのレコードの、
  2. どのフィールドで
  3. どんな値に
変更されたのか?という情報は必要になってきます。今回はその情報を取り出すだけで、データをポストするところまで組んでいません。
tbar:[
{ text: 'touch', handler:function(){
    grid.getStore().each( function( targetObj ){
        var touchField = targetObj.getChanges();
        for( name in touchField ){
            alert(
                "index : [ " + targetObj.id + " ]\n" + 
                "fieldName : [ " + name + " ]\n" +
                "value : [ " + touchField[ name ] +" ]\n" 
            );
        }
        targetObj.commit();
    });
}}]
というわけで、実装の解説を進めていきますが、tbarというコンフィグオプションは前回のTreePanelのときに解説しましたツールバーです。今回はツールバーにtouchというボタンを与えてあげて、そこにハンドラとして編集セルを見るメソッドを用意しました。
まず、gridが用意しているgetStore()メソッドを呼び出して、データストアを取得します。次に返ってきたstoreで持っているeachメソッドを使って、レコード単位に全てのオブジェクトを拾いあげます。
grid.getStore().each( function( targetObj ){
パラメータのtargetObjはExt.data.Recordのオブジェクトが入ってきますので、このオブジェクトに変更があったかどうかを聞きます。
var touchField = targetObj.getChanges();
getChanges()メソッドはAPIDocに以下のような説明がありました。
Gets a hash of only the fields that have been modified since this Record was created or commited.
「レコードが作られたか、あるいは、コミットされた後に編集されたフィールドをハッシュ(オブジェクト)で返すよー」と言っているみたいです。なるほど。便利。編集されてなければ返されたオブジェクトはプロパティを持たないようです。ですので、for~inで調べてみました。これで、編集されたフィールドと値を取得することが出来ます。
ちなみに、targetObjの実態はExt.data.Recordですので、idを持っていて自分がどのレコードかを知っているのですが、今回の実装はストアを作るときに明示的にidを振っています。
    var id = 0;
    var reader = new Ext.data.ArrayReader( { id: 0 }, [
          { name: 'str', mapping: 1 },
       { name: 'num', mapping: 2 }
    ]);
    var store = new Ext.data.Store({
        reader: reader,
        data:[ 
            [ id++, 'hoge', 1 ],
            [ id++, 'moge', 2 ],
            [ id++, 'fuga', 3 ]
        ]
    });
前回作ったGridはSimpleStoreを使って簡単にデータストアを構築しましたが、今回はレコードのidも見たかったのでちょっと構築方法が違います。
ArrayReaderのコンストラクタの第1パラメータで、「レコードのidは扱うデータ(配列)の0番目ですよ」と明示的に指定しています。さらに第2引数でレコードのnameと扱うデータ(配列)の何番目かをmappingで指定しています。マッピングをずらすと、grid内にidを表示することも出来ます。idの生成やその一意性は実装依存ですが、自ら生成しなくとも勝手に割り当てられるようです。ただ、一意に割り当ててあげないとバインド出来ませんね。
これでソートしてレコードの位置が変わってもidでバインドできるようになりました。ちなみにレコードが上から何番目か?ってのを知りたい場合は、
grid.getStore().indexOf( targetObj )
というstoreのindexOfでそのレコードが上から何番目に位置するのか聞けます。
で、最後にtargetObj.commit();で編集をコミットしてあげています。

というわけで、EditorGridPanelの解説をしてみました。ワタシの理解を多分に含めておりますので、誤った情報である可能性がありますのでご注意ください。

2008年12月11日

ExtJSでAIRやってみた

ExtGridAir.png ExtJSのエントリはこちらにまとめてあります

ダウンロードページより、アーカイブ(Ext JS 2.2 SDK)をダウンロードして解凍してください。20081211時点のバージョンは ext-2.2 です。
今日は、ExtJSのAIRアプリケーションを解説してみたいと思います。
最近作ったやる夫AIRはHTML1本だけのコンテンツだったのでflexSDKのadtコマンドでパッケージを簡単に作れましたが、ExtJSはスクリプトもスタイルもイメージファイルもたくさんあるので、AIRパッケージを作るのに苦労しそうなので今回はaptanaを使っています。

基本的には、普通にHTMLとExtJSでアプリケーションを作っていって、AIR化するだけなのですが本家のサンプルを見るとHTMLは以下のようにほとんど書いていなかったのでこれを真似して作ってみます。

main.html

<html>
<head>
	<title>ExtGridAIR</title>
	<link rel="stylesheet" type="text/css" href="lib/ext/resources/css/ext-all.css" />
	<link rel="stylesheet" type="text/css" href="lib/ext/air/resources/ext-air.css" />
	<script type="text/javascript" src="lib/air/AIRAliases.js"></script>
	<script type="text/javascript" src="lib/ext/adapter/ext/ext-base.js"></script>
	<script type="text/javascript" src="lib/ext/ext-all.js"></script>
	<script type="text/javascript" src="lib/ext/air/ext-air.js"></script>
	<script type="text/javascript" src="main.js"></script>
</head>
<body>
<span></span>
</body>
</html>
見るとスタイルシートにext-air.cssを追加して、さらにスクリプトにAIRAliases.jsとext-air.jsが使われています。main.jsは以下のとおりになります。
AIRアプリを作る場合は、Ext.air.NativeWindowを使ってウィンドウを構築するようです。さらにViewPortでレイアウトを組むというやり方です。たぶんmain.htmlのエレメントに直接gridやtreeなどをレンダリングしても大丈夫だと思います。が、non-application Sandboxのhtmlをiframeで組んであげる必要が出てきたりします。このsandboxの話は八角研究所のエントリに詳しく載っています

main.js

Ext.onReady( function(){
	(
		new Ext.air.NativeWindow({
			id: 'mainWindow',
			instance: window.nativeWindow,
			width : 316,
			height : 150
		})
	).show();

	new Ext.Viewport({
	    layout:'fit',
	    items: new Ext.grid.GridPanel({
	        store: new Ext.data.SimpleStore({
		        fields: [{ name: 'a' },{ name: 'b' }],
		        data:[[ 'hoge', 1 ],[ 'moge', 2 ],[ 'fuga', 3 ]]
		    }),
	        cm: new Ext.grid.ColumnModel([
		        { id : "gridid", header: "title", sortable: true, dataIndex: 'a' },
		        { header: "number", sortable: true, dataIndex: 'b' }
		    ]),
	        title:'simple-grid',
	        stripeRows:true,
	        view: new Ext.grid.GridView({
	            forceFit:true
	        })		
	    })
	});
});
こんなかんじでViewPortをつかってあげると、デスクトップアプリケーションぽく綺麗にまとまりますね。今回はgirdを1個だけ載せているのでExt.ViewPortのlayoutを'fit'で使っていますが、absolute, accordion, anchor, border, card, column, fit, form, tableなんかで組めるようです。詳しくはExt.ContainerのlayoutConfigを見てください。
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://ns.adobe.com/air/application/1.5">
	<id>com.adobe.example.extGrid</id>
	<filename>extGrid</filename>
	<name>extGrid</name>
	<version>2.0</version>
	<description></description>
	<copyright></copyright>
	<initialWindow>
		<content>extGrid.html</content>
		<title/>
		<systemChrome>standard</systemChrome>
		<transparent>false</transparent>
		<visible>false</visible>
		<minimizable>true</minimizable>
		<maximizable>true</maximizable>
		<resizable>true</resizable>
	</initialWindow>
	<icon>
		<image16x16>icons/AIRApp_16.png</image16x16>
		<image32x32>icons/AIRApp_32.png</image32x32>
		<image48x48>icons/AIRApp_48.png</image48x48>
		<image128x128>icons/AIRApp_128.png</image128x128>
	</icon>
		<fileTypes>
	</fileTypes>
</application>

AIRパッケージ化

airadt.png export adobe air packageをクリックします。AdobeAirPackageExporterがあがるのでnextを押してウィザードに従います。

certificateが空の場合は、ConfigureCertificateという青地の箇所をクリックして証明書を作成します。証明書の作成は、以下のスクリーンショットのように証明書名とパスワード、パブリッシャを設定するだけで作られます。
作られた証明書のパスワードをポップアップ元のDigitalSigning画面で設定してnextを押すことでパッケージに含まれるコンテンツを選べます。

cert.png 選ぶコンテンツは、全部入れれば間違いはありませんが、かなり冗長なファイルも含まれます。ExtJSで利用しているスタイルや画像などを選んでfinishを押すとairパッケージが作成されます。airパッケージをインストールして試してみましょう!

About ColumnModel

ブログ「mojalog labs ExtJS まとめ」のカテゴリ「ColumnModel」に投稿されたすべてのエントリーのアーカイブのページです。過去のものから新しいものへ順番に並んでいます。

次のカテゴリはEditorGridPanelです。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。

Powered by
Movable Type 3.35