HOME > Learning Place >  フォーム

フォーム

FormPanel は、基本の Panel に フォームを操作できる機能が追加されたものです。 FormPanel は、ユーザーの入力するデータを取得する必要がある時に Ext アプリケーション内で利用できます。

それに加えて、FormPanel は、どんな コンテナレイアウト でも使用できるため、フィールドの位置を管理するための便利で柔軟性がある方法を提供します。 FormPanel は、 Model にも連携できるため、サーバーへのデータの送信や読み込みが簡単になります。

内部的には、FormPanel は、入力フィールドの管理、バリデーション、送信、フォームへの読み込みなどのサービスを管理する BasicForm をラップします。このため、BasicForm のコンフィグオプションを FormPanel に直接設定する事ができます。

FormPanel の基本

まず、ユーザーデータを入力するシンプルな FormPanel です。

Ext.create('Ext.form.Panel', {
    renderTo: Ext.getBody(),
    title: 'User Form',
    height: 150,
    width: 300,
    bodyPadding: 10,
    defaultType: 'textfield',
    items: [
        {
            fieldLabel: 'First Name',
            name: 'firstName'
        },
        {
            fieldLabel: 'Last Name',
            name: 'lastName'
        },
        {
            xtype: 'datefield',
            fieldLabel: 'Date of Birth',
            name: 'birthDate'
        }
    ]
});

このフォームは、自身をドキュメントボディーにレンダリングし、 items コンフィグを使って 3つの Field — “First Name”, “Last Name”, “Date of Birth” を定義しています。

この FormPanel では、 defaultType に ‘textfield’ が設定されている事に注目して下さい。 このため、 xtype が指定されていない項目 (このサンプルでは、”First Name” と “Last Name” のフィールド) は、 Text フィールド になります。

その一方、”Date of Birth” フィールドは、xtype に ‘datefield’ が明示的に定義されているため、 日付け Date フィールド になります。Date フィールドは、有効な日付のデータだけが含まれ、日付を選択するために DatePicker も付いています。

フィールド

フィールドのタイプ

Ext JS には、いくつかの標準的なフィールドのタイプが準備されています。 Ext.form.field 名前空間のフィールドはフォームパネルで使用できます。 詳しくは、各フィールドタイプの API ドキュメントをご覧ください。

バリデーション
1. ビルトイン バリデーション

Ext JS はどのタイプのフィールドに対しても、バリデーションをサポートしていて、いくつかのフィールドには、ビルトインのバリデーションルールもあります。

例えば、 Date フィールド に値が入力され、その値が Date に変換できない場合、フィールドの HTML 要素に x-form-invalid-field CSS クラスが追加されます。

必要であれば、この CSS クラスは、 invalidCls コンフィグを使って変更できます。デフォルトのテーマで、invalidCls を追加すると、赤枠とアンダーラインが追加されます。

Invalid フィールド

無効なデータが含まれているフィールドは、エラーメッセージも表示します。デフォルトでは、このメッセージはツールチップとして表示されます。

Invalid Field Hover

msgTarget コンフィグを使うと、簡単にフィールドのエラーメッセージの場所を変更でき、 invalidText コンフィグでエラーメッセージを変更できます。

各フィールドは独自の invalidText の実装とエラーメッセージ内のサポートトークンの切り替えを提供します。

例えば、Date フィールドの invalidText では、”{0}” の部分は、フィールドの値で置き換えられ、”{1}” の部分は、日付の フォーマット. で置き換えられます。

次のコードでは、フィールドの真下にエラーメッセージを配置して、そのエラーメッセージを変更しています。

{
    xtype: 'datefield',
    fieldLabel: 'Date of Birth',
    name: 'birthDate',
    msgTarget: 'under', // location of the error message
    invalidText: '"{0}" bad. "{1}" good.' // custom error message text
}

Custom Error Message

2. カスタム バリデーション

バリデーションの必要条件の中には、ビルトイン バリデーションで実現する事はできないものもあります。カスタムバリデーションを実装する、最も簡単な方法は、 Text フィールドregex コンフィグを使ってバリデーション ルールを適用し、 maskRe コンフィグを使ってフィールドにどんな文字が入力できるかを管理する方法です。 次は、時間を検証するテキストフィールドのサンプルです。

{
    fieldLabel: 'Last Login Time',
    name: 'loginTime',
    regex: /^([1-9]|1[0-9]):([0-5][0-9])(\s[a|p]m)$/i,
    maskRe: /[\d\s:amp]/i,
    invalidText: 'Not a valid time.  Must be in the format "12:34 PM".'
}

上記の方法は、単一のフィールドを検証する時には、うまく動作しますが、カスタムバリデーションが多くのフィールドで共有するアプリケーションには最適ではありません。

The Ext.form.field.VTypes クラスは、再利用できるバリデーションを生成するためのソリューションを提供します。次のように、”time” というカスタム バリデーションを生成できます。

// custom Vtype for vtype:'time'
var timeTest = /^([1-9]|1[0-9]):([0-5][0-9])(\s[a|p]m)$/i;
Ext.apply(Ext.form.field.VTypes, {
    //  vtype validation function
    time: function(val, field) {
        return timeTest.test(val);
    },
    // vtype Text property: The error text to display when the validation function returns false
    timeText: 'Not a valid time. Must be in the format "12:34 PM".',
    // vtype Mask property: The keystroke filter mask
    timeMask: /[\\d\\s:amp]/i
});

カスタム バリデーションが生成された後、 vtype コンフィグを使って、アプリケーション内の Text フィールドで使用できます。

{
    fieldLabel: 'Last Login Time',
    name: 'loginTime',
    vtype: 'time'
}

動作するデモを見たい人は、 バリデーション サンプル で動作するデモをご覧ください。 をご覧下さい。 詳しくは、 VTypes のAPI ドキュメントを参考にして下さい。

データの管理

フォームの送信

サーバーにデータを提出する、最もシンプルな方法は BasicForm. の url コンフィグを使う事です。 FormPanel が BasicForm をラップしているので、BasicForm のコンフィグオプションはどれでも直接 FormPanel に記述できます。

Ext.create('Ext.form.Panel', {
    ...
    url: 'add_user',
    items: [
        ...
    ]
});

BasicForm の submit メソッドを使って、設定された url にデータを送信できます。

Ext.create('Ext.form.Panel', {
    ...
    url: 'add_user',
    items: [
        ...
    ],
    buttons: [
        {
            text: 'Submit',
            handler: function() {
                var form = this.up('form').getForm(); // BasicForm を取得
                if (form.isValid()) { // 送信前にフォームのデータを検証
                    form.submit({
                        success: function(form, action) {
                            Ext.Msg.alert(‘Success’, action.result.msg);
                        },
                        failure: function(form, action) {
                            Ext.Msg.alert(‘Failed’, action.result.msg);
                        }
                    });
                } else { // データが不正であればアラートを表示
                    Ext.Msg.alert('Invalid Data',
                                  'Please correct form errors.')
                }
            }
        }
    ]
});

上記のサンプルでは、ボタンには、フォームの送信をハンドリングする handler コンフィグがあります。 ハンドラー関数は次のアクションを行います:

  1. まず、BasicForm の参照を取得する必要があります。
  2. 次に、全てのフィールドでバリデーション エラーが発生していない事を確認するために、 isValid メソッドを呼び出します。
  3. 最後に、 2つのコールバック関数 — successfailure を渡して submit メソッドを呼び出します。 このコールバック関数内では、action.result は解析された JSON レスポンスを参照します。

上記のサンプルでは、次のような JSON レスポンスを期待しています。

{ "success": true, "msg": "User added successfully" }
フォームを Model に連携する

Model クラスは、様々な種類のデータの表示や、サーバーのデータの取得と更新のために、Ext JS 全体で使われています。 User を表す Model には、User が持つ fields を定義しますし、データの読み込みや保存をする proxy も定義します。

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: ['firstName', 'lastName', 'birthDate'],
    proxy: {
        type: 'ajax',
        api: {
            read: 'data/get_user',
            update: 'data/update_user'
        },
        reader: {
            type: 'json',
            root: 'users'
        }
    }
});

データは、 loadRecord メソッドを使って、 Model から FormPanel に直接読み込む事ができます。

Ext.ModelMgr.getModel('User').load(1, { // load user with ID of "1"
    success: function(user) {
        userForm.loadRecord(user); // Userがロードされたらフォームにロードする
    }
});

この後、データを保存するために、 submit メソッドを使うのではなく、 BasicForm の updateRecord メソッドを使ってフォームデータでレコードを更新し、Model の save で、サーバーにデータを保存します。

Ext.create('Ext.form.Panel', {
    ...
    url: 'add_user',
    items: [
        ...
    ],
    buttons: [
        {
            text: 'Submit',
            handler: function() {
                var form = this.up('form').getForm(), // get the basic form
                    record = form.getRecord(); // get the underlying model instance
                if (form.isValid()) { // 送信前にフォームのデータを検証
                    form.updateRecord(record); // フォームデータでレコードを更新
                    record.save({ // レコードをサーバーに保存
                        success: function(user) {
                            Ext.Msg.alert('Success', 'User saved successfully.')
                        },
                        failure: function(user) {
                            Ext.Msg.alert('Failure', 'Failed to save user.')
                        }
                    });
                } else { // データが不正であればアラートを表示
                    Ext.Msg.alert('Invalid Data', 'Please correct form errors.')
                }
            }
        }
    ]
});

Model 連携のサンプル

レイアウト

レイアウトは、Ext JS アプリケーションで、コンポーネントの配置やサイズ変更を管理するために使用されます。 FormPanel は、どの コンテナレイアウト. でも使用できます。詳しくは、 Layouts and Containers Guide. をご覧ください。

例えば、 HBox レイアウトを使うと、フォーム内でフィールドを簡単に横に配置できます。

Ext.create('Ext.form.Panel', {
    renderTo: Ext.getBody(),
    title: 'User Form',
    height: 120,
    width: 585,
    defaults: {
        xtype: 'textfield',
        labelAlign: 'top',
        padding: 10
    },
    layout: {
        type: 'hbox'
    },
    items: [
        {
            fieldLabel: 'First Name',
            name: 'firstName'
        },
        {
            fieldLabel: 'Last Name',
            name: 'lastName'
        },
        {
            xtype: 'datefield',
            fieldLabel: 'Date of Birth',
            name: 'birthDate'
        }
    ]
});

Ext JS 5 コンポーネント − 公式ガイド翻訳

Learning Placeトップに戻る

PAGETOP