表单面板 不过是一个基本的添加表单的 面板. 只要有从用户那里收集数据的Ext 应用程序 就有表单面板的使用.
除此之外, 表单面板可以使用任何 容器布局, 提供一种灵活便捷的方式处理字段显示的位置. 表单面板还可以被绑定到 模型, 使得很容易从服务器加载或提交数据.
Form Panel之下封装着一个处理所有的输入, 验证, 提交, 和从服务器加载数据的Basic Form . 这意味着许多Basic Form的配置选项可以直接应用于Form Panel上.
Basic Form
开始之前,看一个如何创建一个简单收集用户数据的表单例子:
Ext.create('Ext.form.Panel', {
renderTo: document.body,
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'
}
]
});
这个表单呈现有三个字段 - “First Name”, “Last Name”, 和 “Date of Birth”. 使用items 配置项把字段都添加到表单面板里.
fieldLabel 配置项定义了字段旁边的标签显示文本, 以及name 配置项变成了基本的HTML字段的name
属性.
请注意Form Panel有一个defaultType(缺省类型)‘textfield’.这意味着任何没有指定xtype(例子中的 “First Name” 和 “Last Name” 字段)的项, 都是 Text Field(文本输入控件).
反之,“Date of Birth” 字段,xtype
明确的被配置成‘datefield’, 使得它是一个Date Field(日期字段). 日期字段(Date Fields)期望只包含有效的日期数据和选择日期的DatePicker(日期选择器).
Fields(字段)
Field Types(字段类型)
Ext JS 提供了一组标准的字段类型. 任何在Ext.form.field
命名空间下的字段都可以在Form Panel(表单面板)中使用. 更多信息请看每一种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 内置了支持任何类型的Field(字段)的验证,并且有些Fields(字段)内置了验证规则.
例如, 如果在Date Field输入了一个不能被转换为Date
的值, 这个Field(字段)的HEML元素将会被添加一个x-form-invalid-field
CSS样式.
如果有必要, 这个CSS样式可以通过invalidCls 配置项修改.补充的invalidCls
给输入(Field)字段添加了一个红色的边框(以及一条红色的无效下划线(“invalid underline”)标识当使用经典主题):
当一个Field(字段)包含无效的数据时,它将展现一个错误的消息. 默认情况下,错误消息会以提示信息的方式展现:
通过msgTarget 配置项可以很容易的更改Field’s(字段的)错误信息展现的位置, 以及invalidText 配置项可以改变错误消息.
每一个字段(Field)都提供了自己的invalidText
实现, 并且许多都支持在错误消息中标识替换(token replacement).
例如, 在Date Field’s(日期输入控件的) invalidText
里, 任何出现“{0}”的地方都将被替换成输入框的值, 任何 出现“{1}”的地方都将被替换成要求的日期格式format.
下面的代码示范如何直接向错误消息直接放置在Field(控件)下面, 并且自定义错误消息文本:
{
xtype: 'datefield',
fieldLabel: 'Date of Birth',
name: 'birthDate',
msgTarget: 'under', // location of the error message
invalidText: '"{0}" bad. "{1}" good.' // 自定义错误消息文本
}
2. 自定义验证
有些验证需求,内置的验证无法满足. 最简单的方法就是使用Text Field’s(文本输入控件) regex配置项应用验证规则和使用maskRe 配置项限制哪些字符可以在控件里输入去实现一种自定义验证. 这里是一个验证时间的文本输入控件的例子.
{
xtype: 'textfield',
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".'
}
虽然上面的方法适用于验证单个的(输入控件)field,但对于一个有许多共享相同自定义验证的输入控件的应用程序来说,这是不切实际的.
Ext.form.field.VTypes类提供了一个创建可重用的自定义验证的解决方案. 下面展示一个自定义的时间验证器如何被创建:
// 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 属性: 当验证方法返回false的时候显示错误文本信息
timeText: 'Not a valid time. Must be in the format "12:34 PM".',
// vtype Mask 属性: 按键过滤
timeMask: /[\d\s:amp]/i
});
一旦一个自定义的验证器被创建了,就可以应用于所有的文本输入控件通过使用vtype 配置项:
{
fieldLabel: 'Last Login Time',
name: 'loginTime',
vtype: 'time'
}
请看一个演示的验证例子. 更多关于自定义验证的信息, 请查阅VTypes的API文档.
数据处理
表单提交
提交数据到服务器最简单的一种方法是使用Basic Form的url配置项. 由于Form Panel 封装了Basic Form,所以我们可以直接在Form Panel上使用任何Basic Form的配置项:
Ext.create('Ext.form.Panel', {
...
url: 'add_user',
items: [
...
]
});
Form的submit 方法可被用于提交数据到配置的url
:
Ext.create('Ext.form.Panel', {
...
url: 'add_user',
items: [
...
],
buttons: [
{
text: 'Submit',
handler: function() {
var form = this.up('form'); // 获取 form
if (form.isValid()) { // 提交数据之前确保Form包含有效数据
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.')
}
}
}
]
});
上面的例子, 一个button被配置了一个 handler 处理form提交任务. 这个handler采取如下措施:
- 首先, 必须获得Form Panel的引用.
- 然后,提交数据之前调用isValid 方法确认没有输入控件有验证错误.
- 最后,调用
submit
方法, 传递两个回调-success
和failure
. 在这些回调函数里,action.result
指解析成JSON的回应.
上面的例子预期的JSON回应看起来像这样:
{ "success": true, "msg": "User added successfully" }
Binding a Form to a Model
The Model 类的使用遍及 Ext JS,描述各种类型的数据以及在服务器上检索和更新数据. 一个描述一个User 的模型应该定义一个User有的所有fields(字段)以及加载和保存数据的proxy:
Ext.define('MyApp.model.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'
}
}
});
数据可以直接被加载到一个 Form Panel 从Model中通过使用loadRecord 方法:
MyApp.model.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
}
});
最后, 替换submit 方法保存数据, Form Panel的updateRecord 方法被用于更新记录与表单数据, 并且 Model的save 方法被调用保存数据到服务器:
Ext.create('Ext.form.Panel', {
...
url: 'add_user',
items: [
...
],
buttons: [
{
text: 'Submit',
handler: function() {
var form = this.up('form'), // get the form panel
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
布局在一个Ext JS应用程序里是用来处理组件的大小和位置的. Form Panels 可以使用任何 布局容器. 更多关于Layouts的信息请查阅布局和容器 指导.
例如, 可以很容易完成在一个表单里水平定位一个控件通过使用HBox 布局:
Ext.create('Ext.form.Panel', {
renderTo: document.body,
title: 'User Form',
height: 120,
width: 585,
defaults: {
xtype: 'textfield',
labelAlign: 'top',
padding: 10
},
layout: 'hbox',
items: [
{
fieldLabel: 'First Name',
name: 'firstName'
},
{
fieldLabel: 'Last Name',
name: 'lastName'
},
{
xtype: 'datefield',
fieldLabel: 'Date of Birth',
name: 'birthDate'
}
]
});