連載
» 2007年11月08日 00時00分 公開

パターンとライブラリで作るAjaxおいしいレシピ(3):Ext JSとprototype.jsで作るリッチなUI (3/4)

[志田裕樹,アークウェブ株式会社]

コントローラーのコード全体を見てみよう

 次に、コントローラー「controllers/extform/form_controller.js」のコードを見てみましょう。

//名前空間オブジェクト
var extform = new Object();
extform.FormController = Class.create();

extform.FormController.prototype = {
    form: null,
    // コンストラクタ
    initialize: function(name) {
        // A:ページがロードされた
        Event.observe(window, 'load', function(){
            // A−1:Extでフォームをリッチに表示するようにビューに依頼
            this.form = extform.FormView.applyExt();
            // A−2:都道府県が選択されたときのイベントハンドラの登録
            this.form.findField('pref')
                .on('select', this.onSelectPref, this);
            // A−3:送信ボタンが押されたときのイベントハンドラの登録
            Event.observe('send', 'click',
                this.onClickSend.bind(this));
        }.bind(this));
    },

    // B:都道府県が選択された
    onSelectPref: function(event, target) {
        // B−1:対応する市町村を表示するように依頼
        extform.FormView.changeCity(this.form,
            'cities/' + target.data.value + '.json');
    },
    // C:送信ボタンが押された
    onClickSend: function() {
        // C−1:送信内容をダイアログ内で表示するように依頼
        extform.FormView.send(this.form);
    }
}
new extform.FormController();

prototype.jsによるイベント登録処理

 コントローラーのコードはイベントハンドラの設定とビューの呼び出しで構成されています。

 イベントハンドラの設定にはprototype.jsのEvent.observeを使用しています。

           // A−3:送信ボタンが押されたときのイベントハンドラの登録
           Event.observe('send', 'click',
                this.onClickSend.bind(this));

 上記、$('send')のonclickイベントが発生したら、onClickSend()メソッドがコールされるように設定する、という意味になります。

 このようにExtを使う場合もPrototype.jsの機能をこれまでどおり使用できます。このため、Prototype.js用拡張ライブラリなどもExtと同居させて使用できます。

 「this.onClickSend.bind(this)」の「.bind(this)」を指定すると、ハンドラが呼ばれたときの、ハンドル内のthisオブジェクトの実体はextform.FormControllerインスタンスになります。

Ext JS流のイベント登録も使う

 都道府県が選ばれたときのイベントの設定は、Event.observe()ではなく、Ext流のイベント登録の方法を使用しています。

            // A−2:都道府県が選択されたときのイベントハンドラの登録
            this.form.findField('pref')
                .on('select', this.onSelectPref, this);

 都道府県は、Extによってコンボボックスに変換されていますので、従来のテキストボックスとは発生するイベントの種類が異なります。このため、Event.observe()ではなく、Extのon()メソッドでハンドラを設定する必要があります。

 「this.form.findField('pref')」は都道府県のコンボボックスを検索する記述です。「form」はBasicFormインスタンスです。BasicFormについてはビューの解説時にもう一度説明します。

 今回は、都道府県のコンボボックスの「select」イベントに対して、コントローラのonSelectPref()メソッドを登録しました。on()メソッドの第3引数の「this」は、prototype.jsの上記「.bind(this)」と同等の働きをします。

ビューのソースコード(Ext JSでフォームをリッチに表示)

 次に、ビューのソースコード「javascripts/views/extform/form_view.js」を確認しましょう。

 まず、「A-1:Extでフォームをリッチに表示するように依頼」に対応するapplyExt()メソッドです。

extform.FormView = {
    // Extでフォームをリッチに表示
    applyExt: function() {
        Ext.QuickTips.init();

        var form = new Ext.form.BasicForm('form');

        var name = new Ext.form.TextField(
            {applyTo: 'name',
            allowBlank: false});

        var prefstore = new Ext.data.SimpleStore(
            {fields: ['value', 'dispvalue'],
            data: [['tokyo', '東京都'],
                ['kanagawa', '神奈川県'],
                ['chiba', '千葉県'],
                ['saitama', '埼玉県']]});
        var pref = new Ext.form.ComboBox(
            {applyTo: 'pref',
            store: prefstore,
            displayField: 'dispvalue',
            valueField: 'value',
            typeAhead: true,
            mode: 'local',
            triggerAction: 'all',
            emptyText: '選択してください',
            selectOnFocus: true});
        var birth = new Ext.form.DateField(
            {applyTo: 'birth',
            format: 'Y/m/d',
            value: '1970/01/01'});
        var introduction = new Ext.form.HtmlEditor(
            {applyTo: 'introduction',
            width: 510,
            height: 200});

        form.add(name, pref, birth, introduction);

        return form;
    },

…(略)…

}

Ext JSの即時入力チェック機構

 Ext JSは入力インターフェイスの入力完了を監視し、即時に入力チェックを行う機能(「LiveFormパターン」)を提供しています。即時入力チェックに関連する記述を抜き出して解説します。

        Ext.QuickTips.init();

        var form = new Ext.form.BasicForm('form');

        var name = new Ext.form.TextField(
            {applyTo: 'name',
            allowBlank: false});

…(略)…

        form.add(name, pref, birth, introduction);

 冒頭の「Ext.QuickTips.init();」は、エラー発生時にエラーメッセージをツールチップ風に表示できるようにする指定です(参考)。

 次に、Ext.form.BasicFormインスタンスを生成し、名前の入力インターフェイスであるExt.form.TextFieldインスタンスを生成して、BasicFormインスタンスに登録しています。

 このTextFieldのような表示要素を、Extでは「コンポーネント」と呼んでいます。Ext.formパッケージ配下には、TextFieldのほか、ComboBoxやRadioやDateFieldなど、さまざまな入力インターフェイス用コンポーネントが用意されています。

 BasicFormのadd()メソッドを使って、入力インターフェイスのコンポーネントを登録すると、その項目に対する入力完了時の即時入力チェックが行われるようになります。BasicFormに登録されたコンポーネントは、コントローラー内でも「form.findField('pref')」のように使用されていましたが、findField()メソッドを使って検索することもできます。

 「名前」のTextFieldコンポーネントを生成する際に指定していた、「allowBlank: false」は、入力必須の指定です。これによって、名前を空のままでフォーカスを外すと、即時にツールチップでエラーが表示されるようになります。

applyToで既存の入力インターフェイスをリッチ化

 「名前」の入力インターフェイスをリッチ化する部分についてもう少し詳しく解説します。

        var name = new Ext.form.TextField(
            {applyTo: 'name',
            allowBlank: false});

 TextFieldコンポーネントをapplyToというオプションを指定して生成しています。「applyTo」は、指定されたDOM要素に対して、TextFieldのコンポーネントを適用する指定です。この記述によって、従来のテキストボックスが、ExtのTextFieldコンポーネントになります。

都道府県をComboBoxコンポーネントに変換

 次に、都道府県をComboBoxコンポーネントに変換する部分を見ていきましょう。関連するソースは次の個所です。

        var prefstore = new Ext.data.SimpleStore(
            {fields: ['value', 'dispvalue'],
            data: [['tokyo', '東京都'],
                ['kanagawa', '神奈川県'],
                ['chiba', '千葉県'],
                ['saitama', '埼玉県']]});
        var pref = new Ext.form.ComboBox(
            {applyTo: 'pref',
            store: prefstore,
            displayField: 'dispvalue',
            valueField: 'value',
   &bbsp;        typeAhead: true,
            mode: 'local',
            triggerAction: 'all',
            emptyText: '選択してください',
            selectOnFocus: true});

 Ext.data.SimpleStoreインスタンスを生成し、Ext.form.ComboBoxコンポーネントを生成する際に、storeオプションにSimpleStoreインスタンスを指定して生成しています。

 ComboBoxの選択肢(<select>タグでいう<option>タグ)は、このようにStoreというクラスのサブクラスのインスタンスを使って指定します。

 Storeとは、表やコンボボックスなどのコンポーネントが表示する元データとして活用されるもので、クライアントサイドのキャッシュ機構を備えており、表のカラム名のような役割をするfields値を、属性として持つ点が特徴として挙げられます。

 Storeは、メモリ内の配列から生成するSimpleStoreや、サーバ上のjsonファイルから生成するJsonStoreなどがあります。今回は下記のようなデータ構造を持つStoreを生成しました。

表2 今回のサンプルで使用したStoreの構造
value dispvalue
tokyo 東京都
kanagawa 神奈川県
chiba 千葉県
saitama 埼玉県

 ComboBox生成時に、「displayField: 'dispvalue'」「valueField: 'value'」という指定をすることで、ComboBoxの表示値を「dispvalue」カラム、選択された際の内部のvalue値を「value」カラムとして指定しています。

 ComboBox生成時のそのほかのオプション値については詳しくはリファレンスを参照してください。

DateFieldコンポーネント、HtmlEditorコンポーネントの適用

 生年月日の項目にはDateFieldコンポーネント、コメントの項目にはHtmlEditorコンポーネントを適用しています。

 DateFieldコンポーネントの生成時の「format: 'Y/m/d'」はカレンダーを使って選択した日付を、テキストで表示する際のフォーマットを指定するものです。これ以外のフォーマットでユーザーが入力をした場合は、即時入力チェックでエラーが表示されます。「value: '1970/01/01'」は初期値を指定しています。

 HtmlEditorコンポーネントの生成時の「width」「height」は、HTMLエディタの横幅、縦幅の指定です。

 さらに次ページでは、ビュー部分でのJSONファイルの扱い方について解説します。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。