A Form Panel is nothing more than a basic Panel with form handling abilities added. Form Panels can be used throughout an Ext application wherever there is a need to collect data from the user. In addition, Form Panels can use any Container Layout, providing a convenient and flexible way to handle the positioning of their fields. Form Panels can also be bound to a Model, making it easy to load data from and submit data back to the server. Under the hood a Form Panel wraps a Basic Form which handles all of its input field management, validation, submission, and form loading services. This means that any of the config options of a Basic Form can be used directly on a Form Panel.
除了表单处理能力,Form Panel没有比Panel再多什么。Form Panels可在Ext app中始终使用,无论是不是需要从user那收集数据。另外,Form Panels 可以使用任何Container Layout,提供方便和灵活的方式来处理字段位置。 Form Panel 也可以绑定到Model,这使得从服务器加载和提交数据非常便利。Form Panel 封装了一个 Basic Form对象,它负责所有输入字段的管理,验证,提交,加载服务。这意味着,任何对于Basic Form的配置项都可直接用于Form Panel.
Basic Form Panel
To start off, here's how to create a simple form that collects user data:
做为开始,这里创建了一个简单的收集用户数据的表单:
Ext.create('Ext.form.Panel', { renderTo: Ext.getBody(), title: 'User Form', height: 130, 280, bodyPadding: 10, defaultType: 'textfield', items: [ { fieldLabel: 'First Name', name: 'firstName' }, { fieldLabel: 'Last Name', name: 'lastName' }, { xtype: 'datefield', fieldLabel: 'Date of Birth', name: 'birthDate' } ] });
This form renders itself to the document body and has three Fields - "First Name", "Last Name", and "Date of Birth". Fields are added to the Form Panel using the items configuration. The fieldLabel configuration defines what text will appear in the label next to the field, and the name configuration becomes the name
attribute of the underlying html field. Notice how this Form Panel has a defaultType of 'textfield'. This means that any of its items that do not have an xtype specified (the "First Name" and "Last Name" fields in this example), are Text Fields. The "Date of Birth" field on the other hand has itsxtype
explicitly defined as 'datefield' which makes it a Date Field. Date Fields expect to only contain valid date data, and come with a DatePicker for selecting a date.
form将自己渲染到document body,具有三个字段: "First Name", "Last Name", and "Date of Birth"。字段通过form 的items配置添加到form。fieldLabel 配置定义了紧邻field的标签显示什么文本,name配置会变为底层html field的name属性。form panel有一个defaultType 'textfield',这意味着任何未指定xtype的field,都是textfield。 "Date of Birth" field的xtype显示定义为'datefield‘,这是一个 Date Field。date field期望仅包含合法的日期数据,并且具有一个DatePicker来选择数据。
See the Simple Form example for a live demo.
Fields
Field Types
Ext JS provides a set of standard Field types out of the box. Any of the Fields in the Ext.form.field
namespace can be used in a Form Panel. For more information see the API documentaion for each Field type:
Ext JS 提供了一套标准的字段类型。任何在Ext.form.field
命名空间的字段都可用于form panel。更多信息可参考每个field type的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
Validation
1. Built-in Validations
Ext JS has built in support for validation on any type of Field, and some Fields have built in validation rules. For example if a value is entered into a Date Field and that value cannot be converted into a Date
, the Field will have the x-form-invalid-field
CSS class added to its HTML element. If necessary, this CSS class can be changed using the invalidCls configuration. In the default theme, adding the invalidCls
adds a red "invalid underline":
Ext JS 对每种类型的field都具有内置的验证支持,有些字段具有内置验证规则。例如,如果一个值被输入到 Date Field,并且这个值不能被转换为日期,字段会具有x-form-invalid-field
css样式类。如果需要,此样式可通过invalidCls来配置。在缺省主题中,显示为一个红色 "invalid underline":
A Field containing invalid data will also display an error message. By default this message displays as a tool tip:
字段包含非法数据还会显示一条错误信息,缺省的这个信息通过tooltip方式显示:
It's easy to change the location of a Field's error message using the msgTarget configuration, and the invalidText configuration changes the error message. Each Field provides its own implementation of invalidText
, and many support token replacement in the error message. For example, in a Date Field'sinvalidText
, any occurrences of "{0}" will be replaced with the Field's value, and any occurrences of "{1}" will be replaced with the required date format. The following code demonstrates placing the error message directly under the Field, and customizing the error message text:
通过msgTarget 配置可以很容易改变错误信息显示的位置,invalidText 配置可改变错误信息。每个字段提供它自己的invalidText实现,并且许多都支持标记替换的错误信息。例如,在日期字段的invalidText,每个出现的 "{0}" 会被替换为实际的值,并且任何出现的"{1}"会被替换为要求的日期格式。下面的代码演示了,将错误信息直接放在field下面,并自定义了错误信息显示文本:
{ 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. Custom Validations
Some validation requirements cannot be met using the built-in validations. The simplest way to implement a custom validation is to use the Text Field'sregex configuration to apply validation rules, and the maskRe configuration to limit which characters can be typed into the field. Here's an example of a Text Field that validates a time.
一些验证需求用内置的验证规则不能满足。最简单的实现自定义验证的方式是使用text field的regex 配置来实施验证规则,maskRe配置可限制哪些字符可以被输入到field。下面是一个text field例子来验证一个时间。
{ fieldLabel: 'Last Login Time', name: 'loginTime', regex: /^([1-9]|1[0-9]):([0-5][0-9])(s[a|p]m)$/i, maskRe: /[ds:amp]/i, invalidText: 'Not a valid time. Must be in the format "12:34 PM".' }
While the above method works well for validating a single field, it is not practical for an application that has many fields that share the same custom validation. The Ext.form.field.VTypes class provides a solution for creating reusable custom validations. Here's how a custom "time" validator can be created:
上面的方法对单个字段工作的很好,但是对于一个app来说,许多字段共用同一个验证的情况,这不是个好办法。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: /[ds:amp]/i });
Once a custom validator has been created it can be used on Text Fields throughout an application using the vtype
configuration:
一旦创建了自定义验证器,就可以通过vtype配置在整个app中使用:
{ fieldLabel: 'Last Login Time', name: 'loginTime', vtype: 'time' }
See Validation Example for a working demo. For more information on custom validations please refer to the API Documentation for VTypes.
真实demo参考 Validation Example。关于自定义验证的更多信息参考api文档的VTypes.
Handling Data
Submitting a Form
The simplest way to submit data to the server is to use the url configuration of Basic Form. Since Form Panel wraps a Basic Form, we can use any of Basic Form's configuration options directly on a Form Panel:
提交数据到服务器的最简单方式是使用Basic Form的url配置。由于Form Panel 包裹了一个Basic Form,我们可以在form panel中直接使用Basic Form的任何配置项:
Ext.create('Ext.form.Panel', { ... url: 'add_user', items: [ ... ] });
The Basic Form's submit method can be used to submit data to the configured url
:
Basic Form的 submit方法可以用来提交数据到配置的url:
Ext.create('Ext.form.Panel', { ... url: 'add_user', items: [ ... ], buttons: [ { text: 'Submit', handler: function() { var form = this.up('form').getForm(); // get the basic form if (form.isValid()) { // make sure the form contains valid data before submitting 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 { // display error alert if the data is invalid Ext.Msg.alert('Invalid Data', 'Please correct form errors.') } } } ] });
In the above example a button is configured with a handler that handles form submission. The handler takes the following actions:
在上面的示例中,一个button被配置了一个handler来处理表单提交。handler采取了下列操作:
- First a reference to the Basic Form must be acquired.首先获得basic form的对象
- Then the isValid method is called before submission to verify that none of the fields have validation errors.调用 isValid方法来验证没有错误
- Finally the
submit
method is called, and two callback functions are passed -success
andfailure
. Within these callback functionsaction.result
refers to the parsed JSON response.最后,调用submi方法,传入两个回调函数success
andfailure。在这些回调函数中,
action.result指向解析后的json响应。
The above example expects a JSON response that looks something like this:
上面的例子期望一个json响应,类似下面这样:
{ "success": true, "msg": "User added successfully" }
Binding a Form to a Model
The Model class is used throughout Ext JS for representing various types of data, as well as retrieving and updating data on the server. A Model representing a User would define the fields a User has, as well as a proxy for loading and saving data:
model类在Ext JS中始终使用,来表示各种类型的数据,包括从服务器获取和提交数据。表示User的model要定user具有的字段,也要定义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' } } });
For more details on working with Models please refer to the Data Guide.
关于model的更多细节请参考 Data Guide.
Data can be loaded into a Form Panel directly from a Model using the loadRecord method:
数据可通过 loadRecord 方法,直接将model加载到form panel
Ext.ModelMgr.getModel('User').load(1, { // load user with ID of "1" success: function(user) { userForm.loadRecord(user); // when user is loaded successfully, load the data into the form } });
Finally, instead of using the submit method to save the data, Basic Form's updateRecord method is used to update the record with the form data, and the Model's save method is called to save the data to the server:
最后,作为submit方法提交数据保存的替换,basic form的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()) { // make sure the form contains valid data before submitting form.updateRecord(record); // update the record with the form data record.save({ // save the record to the server success: function(user) { Ext.Msg.alert('Success', 'User saved successfully.') }, failure: function(user) { Ext.Msg.alert('Failure', 'Failed to save user.') } }); } else { // display error alert if the data is invalid Ext.Msg.alert('Invalid Data', 'Please correct form errors.') } } } ] });
Layouts
Layouts are used to handle sizing and positioning of components in an Ext JS application. Form Panels can use any Container Layout. For more information on Layouts please refer to the Layouts and Containers Guide.
布局被用来处理ext js app中组件的大小和位置。Form Panels可使用任何 Container Layout,更多信息参考Layouts and Containers Guide
For example, positioning fields in a form horizontally can easily be done using an HBox Layout: Container Layout
例如,在表单中水平摆放字段可通过hbox布局简单的做到:
Ext.create('Ext.form.Panel', { renderTo: Ext.getBody(), title: 'User Form', height: 100, 515, 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' } ] });
See the Layout Example for a live demo.