HOME > Learning Place >  No.3 コンポーネントの利用 – (3)フォーム

No.3 コンポーネントの利用 – (3)フォーム

前回までの2回で、画面の左側と中央部を定義しました。 コンポーネントもデータビューとグリッドを使いましたね。

今回は、社員の情報を表示、編集するためにフォームを使ってみましょう。

フォームパネル

フォームパネル (Ext.form.Panel) は、その名の通りフォームとして利用できるパネルです。 フォームパネルでは、HTML の<form> タグが生成されます。 ですから通常の HTML 同様に POST/GET でサーバーにデータを送ることができます。 送信方法としては、デフォルトでは XHR (Ajax通信) を使って送信されますが、通常の送信方法を選択することもできます。 また、フォームパネルにはバリデーションの機能も備わっています。 入力された値をチェックして、ユーザーにフィードバックすることができます。

BasicForm

ここで、フォームパネルの構造についてお話ししましょう。 Ext.form.Panel (FormPanel) クラスの背後には、 Ext.form.Basic クラス (BasicForm) があります。 こちらはフォームパネルのフォームとしての動作の部分を司るクラスです。 FormPanel 内のフィールド操作や、サブミットなどは、 BasicForm が管理します。

Ext.form.Panel クラスのコンフィグオプションには、 Ext.form.Basic がサポートするコンフィグオプションを指定することができ、それらはそのまま 内部的に生成される Ext.form.Basic に渡されます。

Ext.form.Panel クラスの getForm メソッドを使うと、 Ext.form.Basicオブジェクトを取得することができます。 BasicForm の主立ったメソッドは、FormPanel で再定義されているので、FormPanel から直接使うことができますが、再定義されていないメソッドを使うようなときは、このようにして BasicForm を取得します。

  • フィールドのバリデーション管理も、このExt.form.Basicが担当します。isValidメソッドを利用することで、フィールド全体のバリデーション結果を取得することが可能です。
  • データ送信は、submitメソッド、リセットは、resetメソッドを利用します。このように通常の<form>タグの操作を担うのがこのExt.form.Basicになります。

同様にイベントに関しても、BasicForm によって発火される以下のイベントを、 FormPanel が再発火します。

  • beforeaction
  • actionfailed
  • actioncomplete
  • validitychange
  • dirtychange

フォームデータの取得

getValues メソッドを呼び出すと、内部のフィールドの値をキーバリューペアのオブジェクトで取得することができます。 その際のキーになるのが、フィールドの “name” コンフィグオプションです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    var form = Ext.create('Ext.form.Panel', {
        title: 'Test Form',
        width: 500,
        bodyPadding: 5,
        defaultType: 'textfield',
 
        items: [{
            name: 'text1',
            fieldLabel: 'Text1'
        },{
            name: 'text2',
            fieldLabel: 'Text2'
        }],
 
        buttons: [{
            text: 'Submit',
            handler: function() {
                // フォームデータの取得
                console.log(form.getValues());
            }
        }],
        renderTo: Ext.getBody()
    });

このフォームを開いて、Submit ボタンをクリックすると、コンソールに取得した値が記録されます。

1
    Object {text1: "aaa", text2: "bbb"}

Sencha Fiddle で開く

フォームデータの設定

逆にフォームに値を設定するのも簡単にできます。 BasicForm の setValues メソッドにオブジェクトを渡すと、フォームに配置されたフィールドに値を設定することができます。 このメソッドは、getValues のように FormPanel で再定義されていないので、BasicForm を取得して使います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    var form = Ext.create('Ext.form.Panel', {
        title: 'Test Form',
        width: 500,
        bodyPadding: 5,
        defaultType: 'textfield',
 
        items: [{
            name: 'text1',
            fieldLabel: 'Text1'
        },{
            name: 'text2',
            fieldLabel: 'Text2'
        }],
 
        buttons: [{
            text: 'Set Data',
            handler: function() {
                // フォームにデータを設定
                form.getForm().setValues({
                    text1: 'foo',
                    text2: 'Bar'
                })
            }
        }],
        renderTo: Ext.getBody()
    });

このフォームを開いて、Submit ボタンをクリックすると、コンソールに取得した値が記録されます。

Sencha Fiddle で開く

社員のデータ詳細を表示するフォームを作成

では、前回まで作ってきたプロジェクトにフォームを追加しましょう。 画面の下側 (south リージョン) にフォーム (Form.js) を表示します。

まず、view ディレクトリに Form.js を作ります。 これがフォームのビューになります。

app/view/Form.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Ext.define('SlView.view.Form', {
    extend: 'Ext.form.Panel',
    alias: 'widget.myform',
 
    requires: [
        'Ext.form.field.ComboBox'
    ],
 
    bodyPadding: 10,
    title: '詳細',
 
    items: [{
        xtype: 'textfield',     // 名前のテキストフィールド
        fieldLabel: '名前',
        name: 'name',
        anchor: '100%'
    }, {
        xtype: 'combobox',      // 部署のコンボボックス
        fieldLabel: '部署',
        queryMode: 'local',
        name: 'department_id',
        store: 'Departments',   // リストに表示するストア
        displayField: 'name',   // 表示するフィールド
        valueField: 'id',       // 値として使うフィールド
        anchor: '100%'
    }, {
        xtype: 'textfield',     // メールのテキストフィールド
        fieldLabel: 'メール',
        name: 'email',
        anchor: '100%'
    }, {
        xtype: 'combobox',      // 性別のコンボボックス
        fieldLabel: '性別',
        name: 'gender',
        store: {                // リストのストアをインライン指定
            fields: ['text'],
            data:[{
                text: '男'
            }, {
                text: '女'
            }]
        }
    }, {
        xtype: 'numberfield',   // 年齢は数値フィールドで
        fieldLabel: '年齢',
        name: 'age'
    }],
    buttons: [{
        text: '保存'
    }, {
        text: 'キャンセル'
    }]
 
});

このフォームを Main ビューに追加します。 xtypemyform にして、heightプロパティを削除します。 これでフォームの高さに合わせて自動的に設定されます。

app/view/Main.js

27
28
29
30
31
32
33
34
        // south リージョン
        region: 'south',
        xtype: 'myform',    // フォーム
        title: '詳細',
        //height: 200,
        collapsible: true,  // 折りたためるようにする
        collapsed: true,    // 初期状態を折りたたんだ状態にする
        weight: 10          // west が上下一杯使うようにweightを調整

この時点で表示してから、画面下のパネルを開いてみると次の様にフォームが表示されるのがわかります。

バリデーション

Sencha Ext JS のフォームには、非常に強力なバリデーション機能があります。 入力値を即座にチェックしてユーザーにフィードバックできます。 便利でかっこいいフォームが作れますよ。

テキストフィールド (xtype: textfield) のバリデーションをするためのコンフィグには次のものがあります。

  • allowBlank:
    false を設定するとその項目は必須項目になります。
  • minLength:
    文字列の最小の長さを指定します。
  • maxLength:
    文字列の最大長を指定します。
  • regex:
    正規表現を使って値をチェックします。

この他に、vtype コンフィグに値を設定すると、高度なバリデーションを設定できます。 vtype には標準で次の値をセットすることができます。

  • alpha: 英文字のみ
  • alphanum: 英数字のみ
  • email: 電子メールの形式を判定
  • url: URL の形式を判定

これらのバリデーションを設定したフォームを用意しました。

Sencha Fiddle で開く

各フィールドにいろいろ値を入れてみて、エラーメッセージが表示されるのを確認してみてください。

バリデーションの制御

さきほどのエラーメッセージは英語で表示されましたね。 ご安心ください。Ext JS には言語ファイルがありまして、それを使えば日本語にすることができます。 また、エラーメッセージの内容や表示位置も自由に設定できるようになっています。

  • blankText, minLengthText, maxLengthText, regexText を設定すると、エラーメッセージを指定できます。
  • vtypeで指定したバリデーションのエラーメッセージは、vtypeTextコンフィグに設定できます。
  • エラーメッセージの表示位置を指定するには、'msgTarget'コンフィグを設定します。 side, under などが指定できます。
  • デフォルトでは、ユーザーがフィールド入力している時、フィールド値はすぐにバリデーションされます。 これは、 validateOnChange, checkChangeEvents, checkChangeBugger コンフィグで制御することができます。

  • フォームに配置したボタンなどの formBind コンフィグに true を設定すると、フォームのバリデーションの結果によって、そのコンポーネントの有効/無効が切り替わります。

バリデーションの例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var fp = Ext.create('Ext.form.Panel', {
    title: 'バリデーション',
    frame: true,
    bodyPadding: 5,
    width: 500,
    defaultType: 'textfield',
    items: [{
        fieldLabel: '名前',
        allowBlank: false,
        blankText: '名前は省略できません',
        msgTarget: 'side'
    }, {
        fieldLabel: 'URL',
        anchor: '100%',
        vtype: 'url',
        vtypeText: 'URLの形式が不正です',
        msgTarget: 'under'
    }],
    buttons: [{
        text: 'OK',
        formBind: true
    }],
    renderTo: Ext.getBody()
});

メッセージの内容や表示位置を変えています。

Sencha Fiddle で開く

カスタムVType

前記の vtype で指定するバリデーションは、Ext.form.field.VTypes で定義されています。 この Ext.form.field.VTypes にはカスタムの vtype を追加することができます。

カスタムVTypeの例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Ext.apply(Ext.form.field.VTypes, {
    password: function(val, field) {
        if (field.initialPassField) {
            var pwd = field.up('form').down('#' + field.initialPassField);
            return (val == pwd.getValue());
        }
        return true;
    },
    passwordText: 'パスワードが一致しません。'
});
 
Ext.create('Ext.form.Panel', {
    title: 'バリデーション',
    frame: true,
    padding: 10,
    width: 500,
    items: [{
        xtype: 'textfield',
        fieldLabel: 'パスワード',
        inputType: 'password',
        name: 'pass',
        id: 'pass'
    },{
        xtype: 'textfield',
        fieldLabel: 'パスワード確認',
        inputType: 'password',
        name: 'pass-cfrm',
        vtype: 'password',
        initialPassField: 'pass'
    }],
    renderTo: Ext.getBody()
});

Sencha Fiddle で開く

社員フォームを修正

ではプロジェクトの社員フォームにもバリデーションを追加してみましょう。 次の3つのことをやります。どうです?回答はもうおわかりですよね。

  • 名前(name)を必須にする
  • メールアドレスの形式をチェックする
  • エラーがあるときは保存ボタンが押せないようにする。

名前(name)を必須にする

13
14
15
16
17
        xtype: 'textfield',     // 名前のテキストフィールド
        fieldLabel: '名前',
        name: 'name',
        allowBlank: false,      // 名前は必須
        anchor: '100%'

メールアドレスの形式をチェックする

28
29
30
31
32
        xtype: 'textfield',     // メールのテキストフィールド
        fieldLabel: 'メール',
        name: 'email',
        vtype: 'email',         // メール形式チェック
        anchor: '100%'

エラーがあるときは保存ボタンが押せないようにする。

50
51
52
53
54
55
    buttons: [{
        text: '保存',
        formBind: true          // エラーがあるときは押せない
    }, {
        text: 'キャンセル'
    }]

ここまで3回に渡ってコンポーネントを学びながら、画面を作成してきました。 ただ、ここまでのプロジェクトは単にデータを画面に表示しただけで、ユーザーの操作に対応する部分は何もありません。 ユーザーのインタラクションに対応するには、コンポーネントなどのイベントを適切に処理する必要があります。 Sencha の MVC フレームワークでイベント処理を担当するのがコントローラーです。

次回は、コントローラーを使って、作りかけのアプリケーションをユーザー操作に対応させていきます。お楽しみに。

Learning Placeトップに戻る

PAGETOP