Ext2.0中的form使用實例
Ext2.0的form不單增加了時間輸入控件、隱藏輸入控件,還修改了創建方法,通過formpanel代替了原來form,column也根據新的布局定義更新了定義方式。總體來說,定義一個form更簡單便捷了。本文將通過一個實例介紹一下2.0的form的創建以及其大部分控件的使用方法,因水平有限,錯漏難免,忘大家多多諒解!
我們先來看看我們將要設計的form的情況:
呵呵,form有點雜亂,不過在這個fomr里包含了絕大部分Ext2.0的控件,我將會和大家一起探討一下這些控件的使用。
在創建一個form之前,我們先增加以下語句:
Ext.QuickTips.init();
Ext.form.Field.prototype.msgTarget = 'side';
第一句的目的是為需要的元件提供提示信息功能,form的主要提示信息就是客戶端驗證的錯誤信息了。
第二句的目的就是設置控件的錯誤信息顯示位置,主要可選的位置有:
位置值 |
描述 |
qtip |
當鼠標移動到控件上面時顯示提示 |
title |
在瀏覽器的標題顯示,但是測試結果是和qtip一樣的 |
under |
在控件的底下顯示錯誤提示 |
side |
在控件右邊顯示一個錯誤圖標,鼠標指向圖標時顯示錯誤提示 |
[element id] |
錯誤提示顯示在指定id的HTML元件中 |
這個大家可以根據各人喜好設置,我習慣使用“side”,這里有一點要注意的,就是注意控制控件的寬度,以防不夠寬度顯示錯誤圖標,這個下面會說到。
好了,現在創建我們的form,2.0的方法就是直接創建一個formpanel:
var simpleForm = new Ext.FormPanel({
labelAlign: 'left',
title: '表單例子',
buttonAlign:'right',
bodyStyle:'padding:5px',
width: 600,
frame:true,
labelWidth:80,
items: [],
buttons: []
});
simpleForm.render(document.body);
在formpanle里,我們定義了form控件的標題是在左邊的(labelAlign: 'left');form的標題欄顯示標題“表單的例子”;它的按鈕位置是在右對齊的(buttonAlign:'right');邊的類型設置了內補丁 5px(bodyStyle:'padding:5px');總寬度是600px;設置了面板的邊角是圓弧過度的(frame:true),我設置這個屬性主要目的不是因為邊角,而是因為背景,如果不設置這個,背景顏色將為白色,設置了這個將會加入海藍色的背景圖,好看點;還設置了form控件的標題寬度是80px(labelWidth:80)。還有一些其它的設置選項,我這里就不多說,大家可以參看2.0的API。
items數組的設置是我們的重點了,form上的所有控件都是在這里設置的。
從form的結構圖中看到,form整體上是分了兩列的(實際上不是的,呵呵)。因為要分列,所以要使用columnLayout類。在使用 columnLayout類之前,我們需要了解一下CSS中float屬性的作用,改屬性主要作用是設置對象是否及如何浮動,屬性值為none、left 和right三個。column設置是left,意思就是對象浮在左邊的。那這個有什么作用呢?其實這個和我們在word中輸入文字,默認文字是左對齊的,當一行文字的寬度超過頁面的寬度時將自動換行是一樣的。 我們通過一個例子來說明一下。
首先我們定義一個div,背景色是黑色,寬度和高度都是200:
<div style='background:black;width:200px;height:200px;'>
</div>
然后在里面加入2個div,每個寬度和高度都是200,背景色一個是紅色,一個是綠色:
<div style='background:black;width:200px;height:200px;'>
<div style='background:red;width:50px;height:50px;'></div>
<div style='background:green;width:50px;height:50px;'></div>
</div>
我們來看看效果:
在沒有使用float之前,兩個子div是分別各占一行的。好,現在我們在兩個子div中加入“float:left”在看看效果:
<div style='background:black;width:200px;height:200px;'>
<div style='background:red;width:50px;height:50px;float:left;'></div>
<div style='background:green;width:50px;height:50px;float:left;'></div>
</div>
兩個子div出現在同一行了。我們復制一下兩個子div,粘貼兩次,然后看看效果:
<div style='background:black;width:200px;height:200px;'>
<div style='background:red;width:50px;height:50px;float:left;'></div>
<div style='background:green;width:50px;height:50px;float:left;'></div>
<div style='background:red;width:50px;height:50px;float:left;'></div>
<div style='background:green;width:50px;height:50px;float:left;'></div>
<div style='background:red;width:50px;height:50px;float:left;'></div>
<div style='background:green;width:50px;height:50px;float:left;'></div>
</div>
6個子div有序的按左對齊方式排列在一起了,當一行的子div的寬度超過了父div的寬度時,子div自動換行到了第二行。
不知道大家是否看得明白?看不明白自己再動手改變一下子div的寬度和高度,看看效果。column的工作方式就是這樣的。明白這個很重要,因為在定義checkbox和radio的時候,如果想它們的選項在同一行,就要注意column的寬度,不然就無法讓他們在同一行。不過現在column是通過百分比來定義寬度的,我們只要控制好百分比就行了。
好了,我們繼續寫form,因為要用到column,所以我們先在formpanel的itmes加入一個column的定義:
{
layout:'column',
border:false,
labelSeparator:':',
items:[]
}
代碼里定義了在這里使用的是columnlayout(layout:'column');沒有邊(border:false);標題的分隔符號我們用中文冒號代替英文的冒號(labelSeparator:':')。coulmnLayout里的控件將定義在items里。
我們首先在items里加入一個常用輸入控件,是用來輸入姓名的:
{
columnWidth:.5,
layout: 'form',
border:false,
items: [{
xtype:'textfield',
fieldLabel: '姓名',
name: 'name',
anchor:'90%'
}]
}
我們設置了該列的寬度占總寬度的50%(columnWidth:.5);在布局里放了一個formlayout用來放置控件(layout: 'form');formlayout也是沒有邊的(border:false)。在formlayout里有一個類型為 textfield'(xtype:'textfield')的輸入控件。控件標題為姓名(fieldLabel: '姓名'),輸入框(input)的name屬性設置“name”(name: 'name'),輸入框的長度為列寬減去標題的寬度后的90%(anchor:'90%'),余下的10%的是給顯示錯誤信息圖標用的。
在加入性別的radio控件時就要注意了,這里需要加入兩個radio,第一radio是有標題的,第二是沒有的,而且兩個radio加起來的寬度應該正好是余下的列寬(50%):
從代碼中可以看到,除了列寬設置為25%外,其它的列設置和第一控件是一樣。Formlayout里加入了一個類型為radio的控件。控件的標題是性別,控件的選擇顯示文本是男(boxLabel:'男),input的name屬性值是sex(name: 'sex'),該控件默認是已選的(checked:true),控件的值(value)是男(inputValue:'男'),input的寬度是 95%。在這里我還設置一個css屬性,頂部的外補丁為5px(style:'margin-top:5px'),原因是為了選擇按鈕和標題對齊,大家可以將該屬性去掉然后看看效果。
第二個raido控件的列設置就有所不同,因為它不需要標題,所以要設置隱藏標題(hideLabels:true),標題的寬度設置為 0(labelWidth:0),還要設置其標題分隔符號為空(labelSeparator:'')。其余的設置和第一個radio的設置沒有不同,只是input的值不同了。
我們已經設置了3列,3列的列寬分別為50%、25%、25%,根據float的原則,下一列將從第二行開始。
在第二行第一列我們要增加的是一個日期選擇控件:
{
columnWidth:.25,
layout: 'form',
border:false,
items: [{
style:'margin-top:5px',
xtype:'radio',
fieldLabel: '性別',
boxLabel:'男',
name: 'sex',
checked:true,
inputValue:'男',
anchor:'95%'
}]
},{
columnWidth:.25,
layout: 'form',
labelWidth:0,
labelSeparator:'',
hideLabels:true,
border:false,
items: [{
style:'margin-top:5px',
xtype:'radio',
fieldLabel: '',
boxLabel:'女',
name: 'sex',
inputValue:'女',
anchor:'95%'
}]
}
{
columnWidth:.5,
layout: 'form',
border:false,
items: [{
xtype:'datefield',
fieldLabel: '出生日期',
name: 'birthday',
anchor:'90%'
}]
}
日期控件的列寬也是50%,列的其它設置沒有變化。控件的類型為datefield,標題是出生日期,input的name屬性是birthday,intput寬度也是設置了90%,出來留出空位給錯誤信息外,還可以讓控件與上一行的姓名的寬度相同,整列看起來比較整齊。
日期控件的設置和普通文本輸入的設置一樣簡單,這里就不多說了。不過要說到的是漢化的問題。在2.0版自帶的本地化文件ext-lang-zh.js中存在一些小bug,我們需要自己修改一下。
首先要修改的是周的顯示,原來的定義是:
因為在日期選擇中顯示的區域不夠寬,只能顯示一個漢字,所以需要將上面定義的把“周”去掉,修改為:
Date.dayNames = [
"周日",
"周一",
"周二",
"周三",
"周四",
"周五",
"周六"
];
Date.dayNames = [
"日",
"一",
"二",
"三",
"四",
"五",
"六"
];
在年份和月份選擇中的按鈕文字還是英文“ok”和“cancel”的,這里我們也需要修改一下:
if(Ext.DatePicker){
Ext.apply(Ext.DatePicker.prototype, {
todayText : "今天",
minText : "日期在最小日期之前",
maxText : "日期在最大日期之后",
disabledDaysText : "",
disabledDatesText : "",
monthNames : Date.monthNames,
dayNames : Date.dayNames,
nextText : '下月 (Control Right)',
prevText : '上月 (Control Left)',
monthYearText : '選擇一個月 (Control Up/Down 來改變年)',
todayTip : "{0} (Spacebar)",
okText : "確定",
cancelText : "取消",
format : "y年m月d日"
});
}
上面定義中黑色字體部分就是要加入的代碼。如果不喜歡默認格式是“y年m月d日”,需要修改:
if(Ext.form.DateField){
Ext.apply(Ext.form.DateField.prototype, {
disabledDaysText : "禁用",
disabledDatesText : "禁用",
minText : "該輸入項的日期必須在 {0} 之后",
maxText : "該輸入項的日期必須在 {0} 之前",
invalidText : "{0} 是無效的日期 - 必須符合格式: {1}",
format : "Y-m-d"
});
}
修改DatePicker不會改變DateField的格式的,這個自己根據情況決定,呵呵。
我們繼續,現在需要加入一個學歷的下拉選擇控件。下來選擇控件最重要的一個定義就是數據的定義的,數據定義錯誤,可能得不到我們需要的效果,也是很多朋友感覺最麻煩的地方。
{
columnWidth:.5,
layout: 'form',
border:false,
items: [{
xtype:'combo',
store: new Ext.da
{
fields: ["retrunValue", "displayText"],
da
}),
valueField :"retrunValue",
displayField: "displayText",
mode: 'local',
forceSelection: true,
blankText:'請選擇學歷',
emptyText:'選擇學歷',
hiddenName:'education',
editable: false,
triggerAction: 'all',
allowBlank:false,
fieldLabel: '學歷',
name: 'education',
anchor:'90%'
}]
}
列的定義就不說了,沒變化。在items里,類型設置成combo了,在這里定義了一個sotre屬性,就是選擇值存儲的地方,因為是在客戶端的數據,所以使用了一個簡單存儲(SimpleStore)。在存儲里,我們通過一個數組定義了retrunValue和displayText兩個字段。 retrunValue字段指定是提交給后臺的值,displayText字段指定是在下拉中顯示的選擇值。然后我們在da
下面就是很重要的一步了,設置下拉選擇框的值和顯示文本。本例中設置了下拉選擇框的提交值對象的是存儲中的retrunValue字段(valueField :"retrunValue"),顯示文本是存儲中的displayText字段(displayField: "displayText"),通過這兩個設置就可將存儲中的數據和下拉框對應起來。
因為數據是在本地,所以設置了模式為local(mode: 'local')。該下拉列表只允許選擇,不允許輸入(editable: false),而且是必須選擇一個選項(forceSelection: true)。在沒有選擇值時顯示為選擇學歷(emptyText:'選擇學歷')。提交form時,該項如果沒有選擇,則提示錯誤信息“請選擇學歷” (blankText:'請選擇學歷')。該選項值不允許為空(allowBlank:false)。大家要注意的是hiddenName和name屬性,name只是改下拉的名稱,作用是可通過,而hiddenName才是提交到后臺的input的name。如果沒有設置hiddenName,在后臺是接收不到結構的,這個大家一定要注意。
因為這個下拉是只能選擇的,所以一定要設置屬性triggerAction為all,不然當你選擇了某個選項后,你的下拉將只會出現匹配選項值文本的選擇項,其它選擇項是不會再顯示了,這樣你就不能更改其它選項了。
如果要為控件設置默認值,就設置屬性value,value的值要設置為提交給后臺的值,不要設置為顯示文本。例如本例要設置大學為默認值得,則設置value的值為6。
現在到第三行了,我們要創建一個checkbox選項輸入:
{
columnWidth:.35,
layout: 'form',
border:false,
items: [{
xtype:'checkbox',
fieldLabel: '權限組',
boxLabel:'系統管理員',
name: 'popedom',
inputValue:'1',
anchor:'95%'
}]
},{
columnWidth:.2,
layout: 'form',
labelWidth:0,
labelSeparator:'',
hideLabels:true,
border:false,
items: [{
xtype:'checkbox',
fieldLabel: '',
boxLabel:'管理員',
name: 'pepedom',
inputValue:'2',
anchor:'95%'
}]
},{
columnWidth:.2,
layout: 'form',
labelWidth:0,
labelSeparator:'',
hideLabels:true,
border:false,
items: [{
xtype:'checkbox',
fieldLabel: '',
boxLabel:'普通用戶',
name: 'pepedom',
inputValue:'3',
anchor:'95%'
}]
},{
columnWidth:.25,
layout: 'form',
labelWidth:0,
labelSeparator:'',
hideLabels:true,
border:false,
items: [{
xtype:'checkbox',
fieldLabel: '',
boxLabel:'訪客',
name: 'pepedom',
inputValue:'4',
anchor:'95%'
}]
}
checkbox的設置和radio的設置大同小異,大家注意列寬的定義就行。
第四行的兩個輸入框主要是測試通過vtypes屬性來驗證輸入框的輸入的:
{
columnWidth:.5,
layout: 'form',
border:false,
items: [{
xtype:'textfield',
fieldLabel: '電子郵件',
name: 'email',
vtype:'email',
allowBlank:false,
anchor:'90%'
}]
},{
columnWidth:.5,
layout: 'form',
border:false,
items: [{
xtype:'textfield',
fieldLabel: '個人主頁',
name: 'url',
vtype:'url',
anchor:'90%'
}]
}]
}
這里的定義和普通的文本輸入框沒什么區別,只是多了一個vtypes的屬性定義。Vtypes里總共定義了email、url、alpha和 alphanum四種類型數據格式,email和url這個不用介紹了,呵呵。alpha是字母和下劃線的組合,alphanum是字母、下劃線和數字的組合。
下面要加入一個tabpanel,加入3個tab頁。
{
xtype:'tabpanel',
plain:true,
activeTab: 0,
height:235,
defaults:{bodyStyle:'padding:10px'},
items:[]
}
要注意的是,這個tabpanel不是在上面coulmn的items里加的,因為不在column里。我們加在formpanel里。把item 類型設置為'tabpanel'就行了,然后將標簽頁頭的背景設置為透明的(plain:true),當前活動的標簽頁是第一頁(activeTab: 0),高度設置為235px(height:235),tab頁的面板使用內補丁10px(defaults: {bodyStyle:'padding:10px'})。
好了,現在在tabpanel的items加入標簽頁。第一頁主要有兩個輸入控件,一個是vtypes類型alphanum的登錄輸入框和一個密碼輸入框。
{
title:'登錄信息',
layout:'form',
defaults: {width: 230},
defaultType: 'textfield',
items: [{
fieldLabel: '登錄名',
name: 'loginID',
allowBlank:false,
vtype:'alphanum',
allowBlank:false
},{
inputType:'password',
fieldLabel: '密碼',
name: 'password',
allowBlank:false
}]
}
在標簽定義了,設置了標簽標題是登錄信息(title:'登錄信息'),控件容器是formlayout(layout:'form'),控件的默認寬度是230px(defaults: {width: 230}),默認控件類型是textfield(defaultType: 'textfield')。
兩個控件的定義與前面的textfield定義沒什么區別,只是密碼輸入框需要定義input控件的類型為password(inputType:'password')。兩個控件都不允許為空(allowBlank:false)。
第二個標簽頁里有numberfield、timefield和textfield三個控件:
{
title:'數字時間字母',
layout:'form',
defaults: {width: 230},
defaultType: 'textfield',
items: [{
xtype:'numberfield',
fieldLabel: '數字',
name: 'number'
},{
xtype:'timefield',
fieldLabel: '時間',
name: 'time'
},{
fieldLabel: '純字母',
name: 'char',
vtype:'alpha'
}]
}
Numberfield顧名思義就是只能輸入數字的輸入控件。在該例子,沒做最大值、最小值任何限制,如果要設置最大值和最小值,分別設置 maxValue和minValue兩個屬性就行了。如果要設置數字輸入長度,例如身份證號碼,可以設置maxLength和minLength兩個屬性。可以通過設置maxText、minText、maxLengthText和minLengthText設置各自的驗證出錯信息。可通過 allowDecimals屬性設置是否只允許輸入整型值,默認值是true,允許輸入浮點數。設置allowNegative設置是否只允許輸入正數,默認值是true,允許輸入正負數。通過decimalPrecision屬性可設置小數點后的位數,默認值是2位。
timefield是新增加的時間輸入控件,起彌補日期輸入控件不能輸入時間的作用。它的定義也很簡單,設置類型為timefield就行了。 timefield默認時間格式是12小時制的,我們可通過修改format屬性來修改其數據格式。通過設置increment屬性可設置下拉選擇值得時間區間,默認值是15分鐘的。還可以和數字輸入控件一樣設置最大值和最小值。下拉的設置和combobox是一樣的。
在目前的版本中,timefield類還沒有漢化,所以我們要在本地文件中加入timefield的漢化定義:
if(Ext.form.TimeField){
Ext.apply(Ext.form.TimeField.prototype, {
format:'G:i:s',
minText : "該輸入項的時間必須大于或等于: {0}",
maxText : "該輸入項的時間必須小于或等于: {0}",
invalidText : "{0}不是有效的時間",
});
}
在這里,我默認定義了時間格式是24小時制的,小時為個位數是不加前綴0。
最后一個加入的是測試純字母輸入的,和email等是一樣的,我就不介紹了。
在最后一個tab頁中加入了一個textarea輸入:
{
title:'文本區域',
layout:'fit',
items: {
xtype:'textarea',
id:'area',
fieldLabel:''
}
}
和textfield一樣,只要設置類型為textarea就可以了,唯一的區別是為了讓textarea和面板自適應面板,使用了fitlayout作為它的容器,所以在這里我們不用設置textarea的寬度和高度。
最后一步就是為form添加按鈕了,在formpanel的buttons屬性中我們加入了一個保存按鈕和取消按鈕:
buttons: [{
text: '保存',
handler:function(){
if(simpleForm.form.isValid()){
this.disabled=true;
simpleForm.form.doAction('submit',{
url:'test.asp',
method:'post',
params:'',
success:function(form,act
Ext.Msg.alert('操作',act
},
failure:function(){
Ext.Msg.alert('操作','保存失敗!');
this.disabled=false;
}
});
}
}
},{
text: '取消',
handler:function(){simpleForm.form.reset();}
}]
在formpanel類中,form屬性指向的是formpanle里的basicform對象,我們可通過formpanle.form來使用該 basicform對象。在被例子,我們已經將formpanel對象賦值給了simpleForm這個變量,所以我們可以通過 simpleForm.form訪問面板里的basicform對象。
在buttons里定義的按鈕默認是Ext.Button,所以按鈕的屬性定義可以查看Ext.Button的API。在這里兩個按鈕都沒用到其它屬性,只是設置了顯示文本(text)和單擊事件。
保存按鈕要做的就是先做basicform的客戶端驗證(simpleForm.form.isValid()),驗證通過了則設置該按鈕狀態為 disable,防止2次提交。然后調用simpleForm.form.doAction方法提交數據。doAction方法的第一個參數 “submit”的意思是表示執行的是提交操作,提交的后臺頁面是test.asp(url:'test.asp'),提交方式是 post(method:'post'),沒有其它提交參數(params:''),提交成功后執行success定義的函數,本例只是顯示一個保存成功信息。后臺返回的數據格式是需要我們注意的,一定要json格式,而且必須包含“success:true”,不然不會執行success定義的函數。success 定義的函數返回兩個參數,第一是form本身,第二個是ajax返回的響應結果,在act
取消按鈕就是簡單的reset一下form的控件。
如果想form按以前的老辦法提交,可以在formpanel的定義中加入一下設置:
on
submit: function() { this.getEl().dom.submit();}
第一個設置的目的是取消formpanel的默認提交函數。第二就是設置新的提交方式為舊方式提交。