フォーム
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 ドキュメントをご覧ください。
- Ext.form.field.Checkbox
- Ext.form.field.ComboBox
- Ext.form.field.Date
- Ext.form.field.Display
- Ext.form.field.File
- Ext.form.field.Hidden
- Ext.form.field.HtmlEditor
- Ext.form.field.Number
- Ext.form.field.Radio
- Ext.form.field.Text
- Ext.form.field.TextArea
- Ext.form.field.Time
バリデーション
1. ビルトイン バリデーション
Ext JS はどのタイプのフィールドに対しても、バリデーションをサポートしていて、いくつかのフィールドには、ビルトインのバリデーションルールもあります。
例えば、
Date フィールド
に値が入力され、その値が Date
に変換できない場合、フィールドの HTML 要素に x-form-invalid-field
CSS クラスが追加されます。
必要であれば、この CSS クラスは、
invalidCls
コンフィグを使って変更できます。デフォルトのテーマで、invalidCls
を追加すると、赤枠とアンダーラインが追加されます。
無効なデータが含まれているフィールドは、エラーメッセージも表示します。デフォルトでは、このメッセージはツールチップとして表示されます。
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 } |
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
コンフィグがあります。
ハンドラー関数は次のアクションを行います:
- まず、BasicForm の参照を取得する必要があります。
- 次に、全てのフィールドでバリデーション エラーが発生していない事を確認するために、 isValid メソッドを呼び出します。
- 最後に、
2つのコールバック関数 —
success
とfailure
を渡して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.') } } } ] }); |
レイアウト
レイアウトは、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' } ] }); |