Ext面向?qū)ο箝_(kāi)發(fā)實(shí)踐代碼第1/2頁(yè)
更新時(shí)間:2008年11月18日 00:37:01 作者:
這是自己在學(xué)習(xí)Ext過(guò)程中一個(gè)寫(xiě)的一個(gè)示例程序,僅為練習(xí),功能并不全,現(xiàn)將其記錄在我的博客中,希望可以和學(xué)習(xí)Ext的朋友一起分享
示例程序簡(jiǎn)述:
這個(gè)Demo為了演示如將使用GridPanel顯示數(shù)據(jù),并為GridPanel添加工具條按鈕,提供彈出式窗體新增數(shù)據(jù)。
使用到的Ext組件
這個(gè)Demo涉及到Ext中的GridPanel,F(xiàn)ormPanel和Window三個(gè)組件。
效果圖


現(xiàn)在開(kāi)始講解代碼,首先看一下創(chuàng)建GridPanel的代碼片段
//定義數(shù)據(jù)列表面板類(lèi)
PersonListGridPanel = Ext.extend(Ext.grid.GridPanel, {
insertWin: null,
updateWin: null,
constructor: function() {
//添加自定義事件
this.addEvents("rowSelect");
this.insertWin = new InsertPersonInfoWindow();
this.insertWin.on("submit", this.onInsertWinSubmit, this);
this.updateWin = new UpdatePersonInfoWindow();
this.updateWin.on("submit", this.onUpdateWinSubmit, this);
PersonListGridPanel.superclass.constructor.call(this, {
renderTo: Ext.getBody(),
width: 360,
height: 300,
frame:true,
sm: new Ext.grid.RowSelectionModel({
singleSelect:true,
listeners: {
"rowselect": {
fn: function(sm, rowIndex, r) {
this.fireEvent("rowSelect", r); //觸發(fā)自定義事件
},
scope: this
}
}
}),
store: new Ext.data.JsonStore({
data: [{name: "李宗盛", age: 28, sex: "男"}, {name: "林憶蓮", age: 26, sex: "女"}],
fields: ["name", "sex", "age"]
}),
draggable: false,
enableColumnMove: false,
title: "First Grid",
//iconCls:'icon-grid',
colModel: new Ext.grid.ColumnModel([
{header: "Staff Name", width: 100, menuDisabled: true},
{header: "Age", width: 100, sortable: true, dataIndex: "age", align: "right", tooltip: "這里是提示信息"},
{header: "Sex", width: 100, sortable: true, dataIndex: "sex", align: "center"}
]),
tbar: [{
text: "添加人員",
handler: function() {
//***************************************************
//如果沒(méi)有重寫(xiě)InsertPersonInfoWindow的Close方法
//在調(diào)用之前需要檢查其實(shí)例insertWin是否被釋放
//使用示例:
//if (!this.insertWin) {
// this.insertWin = new InsertPersonInfoWindow();
//}
//this.insertWin.show();
//***************************************************
this.insertWin.show();
},
scope: this
}, "-", {
text: "修改人員",
handler: function() {
var r = this.getActiveRecord();
if (!r) return;
//一定要先調(diào)用Show方法,而后再調(diào)用Load方法,
//否則數(shù)據(jù)不會(huì)被呈現(xiàn)出來(lái)
this.updateWin.show();
this.updateWin.load(r);
},
scope: this
}, "-", {
text: "刪除人員",
handler: function() {
var r = this.getActiveRecord();
if (!r) return;
Ext.MessageBox.confirm("刪除", "刪除當(dāng)前人員信息?", function(btn) {
if(btn == "yes") {
this.delRecord(r);
}
}, this);
},
scope: this
}]
});
},
getActiveRecord: function() {
var sm = this.getSelectionModel();
//沒(méi)有選中的記錄時(shí),是拋出異常還是返回null???????
return (sm.getCount() === 0) ? null : sm.getSelected();
},
insert: function(r) {
this.getStore().add(r);
},
delRecord: function(r) {
this.getStore().remove(r);
},
onInsertWinSubmit: function(win, r) {
this.insert(r);
},
onUpdateWinSubmit: function(win, r) {
alert('onUpdateWinSubmit');
}
});
數(shù)據(jù)維護(hù)面板代碼
//定義數(shù)據(jù)維護(hù)面板,在后面定義的新增和修改窗體中都會(huì)使用到該面板
PersonInfoFormPanel = Ext.extend(Ext.form.FormPanel, {
constructor: function() {
PersonInfoFormPanel.superclass.constructor.call(this, {
//title: "Person Info",
frame: true,
width: 360,
labelWidth: 40,
defaultType: "textfield",
defaults: { anchor: "92%" },
items: [{
name: "name", //注意,這里使用name屬性而不是id,因?yàn)镻ersonInfoFormPanel會(huì)被添加和插入兩個(gè)窗體使用,使用id會(huì)有沖突,導(dǎo)致組件不能被正確顯示
fieldLabel: "Name",
allowBlank: false,
emptyText: "請(qǐng)輸入姓名",
blankText: "姓名不能為空"
}, {
name: "age",
fieldLabel: "Age",
vtype: "age"
}, {
hiddenName: "sex",
xtype: "combo",
fieldLabel: "Sex",
store: new Ext.data.SimpleStore({
fields: [
{name: 'Sex'}
],
data:[["男"], ["女"]]
}),
mode: 'local',
displayField:'Sex',
triggerAction: 'all',
emptyText:'選擇性別...'
}]
})
},
getValues: function() {
if (this.getForm().isValid()) {
return new Ext.data.Record(this.getForm().getValues());
}
else {
throw Error("Error Message");
}
},
setValues: function(r) {
this.getForm().loadRecord(r);
},
reset: function() {
this.getForm().reset();
}
});
對(duì)數(shù)據(jù)的維護(hù)有新增和更新兩個(gè)動(dòng)作,從設(shè)計(jì)的角度來(lái)講就需要編寫(xiě)兩個(gè)窗體對(duì)其進(jìn)行操作。細(xì)心的朋友一定會(huì)想,新增和更新的動(dòng)作都是針對(duì)相同的數(shù)據(jù)表,那么能不能只寫(xiě)一個(gè)窗體,然后復(fù)用呢?答案是肯定的。下面我們就先寫(xiě)一個(gè)窗體基類(lèi)。
//新增,修改窗體基類(lèi)
PersonInfoWindow = Ext.extend(Ext.Window, {
form: null,
constructor: function() {
this.addEvents("submit");
this.form = new PersonInfoFormPanel();
//Ext.apply(this.form, {baseCls: "x-plain"});
PersonInfoWindow.superclass.constructor.call(this, {
plain: true,
width: 360,
modal: true, //模式窗體
onEsc: Ext.emptyFn,
closeAction: "hide",
items: [this.form],
buttons: [{
text: "確 定",
handler: this.onSubmitClick,
scope: this
}, {
text: "取 消",
handler: this.onCancelClick,
scope: this
}]
});
//alert(this.onSubmitClick);
},
close: function() {
//需要重寫(xiě)CLose方法,
//否則在窗體被關(guān)閉其實(shí)體會(huì)被釋放
this.hide();
this.form.reset();
},
onSubmitClick: function() {
//alert(Ext.util.JSON.encode(this.form.getValues().data));
try {
this.fireEvent("submit", this, this.form.getValues());
this.close();
}
catch(_err) {
return;
}
},
onCancelClick: function() {
this.close();
}
});
基類(lèi)寫(xiě)了之后,我們就可以使用繼承的方法來(lái)編寫(xiě)新進(jìn)和更新窗體了。
//定義新增數(shù)據(jù)窗體
InsertPersonInfoWindow = Ext.extend(PersonInfoWindow, {
title: "添加"
});
//==============================================================================
//定義編輯數(shù)據(jù)窗體
UpdatePersonInfoWindow = Ext.extend(PersonInfoWindow, {
title: "修改",
load: function(r) {
this.form.setValues(r);
}
});
為了區(qū)分新增和更新窗體,我們?cè)谄涓髯缘膶?shí)現(xiàn)類(lèi)中為其指定了Title屬性,另外在更新窗體類(lèi)中需要另外添加一個(gè)用于加載待編輯數(shù)據(jù)的方法Load。
腳本部分算是完成了,下面看看如何在HTML中使用。HTML中的引用代碼
<script type="text/javascript">
Ext.QuickTips.init();
Ext.form.Field.prototype.msgTarget = "side";
Ext.BLANK_IMAGE_URL = "http://localhost:8080/ext-2.2/resources/images/default/s.gif";
Ext.apply(Ext.form.VTypes, {
"age": function(_v) {
if (/^\d+$/.test(_v)) {
var _age = parseInt(_v);
if ((_age > 0) && (_age < 200)) return true;
}
return false;
},
"ageText": "年齡必須在0到200之間",
"ageMask": /[0-9]/i
});
Ext.onReady(function() {
new PersonListGridPanel();
});
</script>
代碼很簡(jiǎn)潔,也很清晰。只需要?jiǎng)?chuàng)建一個(gè)PersonListGridPanel即可,因?yàn)樗陨戆诵略?、修改的窗體對(duì)象,而新增和修改窗體中都使用到了負(fù)責(zé)數(shù)據(jù)編輯的PersonInfoFormPanel。
在PersonInfoFormPanel中使用了VTypes進(jìn)行數(shù)據(jù)驗(yàn)證。
新增和修改窗體僅僅是界面,負(fù)責(zé)將用戶(hù)在PersonInfoFormPanel中填寫(xiě)的數(shù)據(jù)傳回到ListGrid中以便保存,或是將ListGrid中的數(shù)據(jù)傳遞到PersonInfoFormPanel中進(jìn)行呈現(xiàn),供用戶(hù)編輯。
這個(gè)Demo為了演示如將使用GridPanel顯示數(shù)據(jù),并為GridPanel添加工具條按鈕,提供彈出式窗體新增數(shù)據(jù)。
使用到的Ext組件
這個(gè)Demo涉及到Ext中的GridPanel,F(xiàn)ormPanel和Window三個(gè)組件。
效果圖


現(xiàn)在開(kāi)始講解代碼,首先看一下創(chuàng)建GridPanel的代碼片段
復(fù)制代碼 代碼如下:
//定義數(shù)據(jù)列表面板類(lèi)
PersonListGridPanel = Ext.extend(Ext.grid.GridPanel, {
insertWin: null,
updateWin: null,
constructor: function() {
//添加自定義事件
this.addEvents("rowSelect");
this.insertWin = new InsertPersonInfoWindow();
this.insertWin.on("submit", this.onInsertWinSubmit, this);
this.updateWin = new UpdatePersonInfoWindow();
this.updateWin.on("submit", this.onUpdateWinSubmit, this);
PersonListGridPanel.superclass.constructor.call(this, {
renderTo: Ext.getBody(),
width: 360,
height: 300,
frame:true,
sm: new Ext.grid.RowSelectionModel({
singleSelect:true,
listeners: {
"rowselect": {
fn: function(sm, rowIndex, r) {
this.fireEvent("rowSelect", r); //觸發(fā)自定義事件
},
scope: this
}
}
}),
store: new Ext.data.JsonStore({
data: [{name: "李宗盛", age: 28, sex: "男"}, {name: "林憶蓮", age: 26, sex: "女"}],
fields: ["name", "sex", "age"]
}),
draggable: false,
enableColumnMove: false,
title: "First Grid",
//iconCls:'icon-grid',
colModel: new Ext.grid.ColumnModel([
{header: "Staff Name", width: 100, menuDisabled: true},
{header: "Age", width: 100, sortable: true, dataIndex: "age", align: "right", tooltip: "這里是提示信息"},
{header: "Sex", width: 100, sortable: true, dataIndex: "sex", align: "center"}
]),
tbar: [{
text: "添加人員",
handler: function() {
//***************************************************
//如果沒(méi)有重寫(xiě)InsertPersonInfoWindow的Close方法
//在調(diào)用之前需要檢查其實(shí)例insertWin是否被釋放
//使用示例:
//if (!this.insertWin) {
// this.insertWin = new InsertPersonInfoWindow();
//}
//this.insertWin.show();
//***************************************************
this.insertWin.show();
},
scope: this
}, "-", {
text: "修改人員",
handler: function() {
var r = this.getActiveRecord();
if (!r) return;
//一定要先調(diào)用Show方法,而后再調(diào)用Load方法,
//否則數(shù)據(jù)不會(huì)被呈現(xiàn)出來(lái)
this.updateWin.show();
this.updateWin.load(r);
},
scope: this
}, "-", {
text: "刪除人員",
handler: function() {
var r = this.getActiveRecord();
if (!r) return;
Ext.MessageBox.confirm("刪除", "刪除當(dāng)前人員信息?", function(btn) {
if(btn == "yes") {
this.delRecord(r);
}
}, this);
},
scope: this
}]
});
},
getActiveRecord: function() {
var sm = this.getSelectionModel();
//沒(méi)有選中的記錄時(shí),是拋出異常還是返回null???????
return (sm.getCount() === 0) ? null : sm.getSelected();
},
insert: function(r) {
this.getStore().add(r);
},
delRecord: function(r) {
this.getStore().remove(r);
},
onInsertWinSubmit: function(win, r) {
this.insert(r);
},
onUpdateWinSubmit: function(win, r) {
alert('onUpdateWinSubmit');
}
});
數(shù)據(jù)維護(hù)面板代碼
復(fù)制代碼 代碼如下:
//定義數(shù)據(jù)維護(hù)面板,在后面定義的新增和修改窗體中都會(huì)使用到該面板
PersonInfoFormPanel = Ext.extend(Ext.form.FormPanel, {
constructor: function() {
PersonInfoFormPanel.superclass.constructor.call(this, {
//title: "Person Info",
frame: true,
width: 360,
labelWidth: 40,
defaultType: "textfield",
defaults: { anchor: "92%" },
items: [{
name: "name", //注意,這里使用name屬性而不是id,因?yàn)镻ersonInfoFormPanel會(huì)被添加和插入兩個(gè)窗體使用,使用id會(huì)有沖突,導(dǎo)致組件不能被正確顯示
fieldLabel: "Name",
allowBlank: false,
emptyText: "請(qǐng)輸入姓名",
blankText: "姓名不能為空"
}, {
name: "age",
fieldLabel: "Age",
vtype: "age"
}, {
hiddenName: "sex",
xtype: "combo",
fieldLabel: "Sex",
store: new Ext.data.SimpleStore({
fields: [
{name: 'Sex'}
],
data:[["男"], ["女"]]
}),
mode: 'local',
displayField:'Sex',
triggerAction: 'all',
emptyText:'選擇性別...'
}]
})
},
getValues: function() {
if (this.getForm().isValid()) {
return new Ext.data.Record(this.getForm().getValues());
}
else {
throw Error("Error Message");
}
},
setValues: function(r) {
this.getForm().loadRecord(r);
},
reset: function() {
this.getForm().reset();
}
});
對(duì)數(shù)據(jù)的維護(hù)有新增和更新兩個(gè)動(dòng)作,從設(shè)計(jì)的角度來(lái)講就需要編寫(xiě)兩個(gè)窗體對(duì)其進(jìn)行操作。細(xì)心的朋友一定會(huì)想,新增和更新的動(dòng)作都是針對(duì)相同的數(shù)據(jù)表,那么能不能只寫(xiě)一個(gè)窗體,然后復(fù)用呢?答案是肯定的。下面我們就先寫(xiě)一個(gè)窗體基類(lèi)。
復(fù)制代碼 代碼如下:
//新增,修改窗體基類(lèi)
PersonInfoWindow = Ext.extend(Ext.Window, {
form: null,
constructor: function() {
this.addEvents("submit");
this.form = new PersonInfoFormPanel();
//Ext.apply(this.form, {baseCls: "x-plain"});
PersonInfoWindow.superclass.constructor.call(this, {
plain: true,
width: 360,
modal: true, //模式窗體
onEsc: Ext.emptyFn,
closeAction: "hide",
items: [this.form],
buttons: [{
text: "確 定",
handler: this.onSubmitClick,
scope: this
}, {
text: "取 消",
handler: this.onCancelClick,
scope: this
}]
});
//alert(this.onSubmitClick);
},
close: function() {
//需要重寫(xiě)CLose方法,
//否則在窗體被關(guān)閉其實(shí)體會(huì)被釋放
this.hide();
this.form.reset();
},
onSubmitClick: function() {
//alert(Ext.util.JSON.encode(this.form.getValues().data));
try {
this.fireEvent("submit", this, this.form.getValues());
this.close();
}
catch(_err) {
return;
}
},
onCancelClick: function() {
this.close();
}
});
基類(lèi)寫(xiě)了之后,我們就可以使用繼承的方法來(lái)編寫(xiě)新進(jìn)和更新窗體了。
復(fù)制代碼 代碼如下:
//定義新增數(shù)據(jù)窗體
InsertPersonInfoWindow = Ext.extend(PersonInfoWindow, {
title: "添加"
});
//==============================================================================
復(fù)制代碼 代碼如下:
//定義編輯數(shù)據(jù)窗體
UpdatePersonInfoWindow = Ext.extend(PersonInfoWindow, {
title: "修改",
load: function(r) {
this.form.setValues(r);
}
});
為了區(qū)分新增和更新窗體,我們?cè)谄涓髯缘膶?shí)現(xiàn)類(lèi)中為其指定了Title屬性,另外在更新窗體類(lèi)中需要另外添加一個(gè)用于加載待編輯數(shù)據(jù)的方法Load。
腳本部分算是完成了,下面看看如何在HTML中使用。HTML中的引用代碼
復(fù)制代碼 代碼如下:
<script type="text/javascript">
Ext.QuickTips.init();
Ext.form.Field.prototype.msgTarget = "side";
Ext.BLANK_IMAGE_URL = "http://localhost:8080/ext-2.2/resources/images/default/s.gif";
Ext.apply(Ext.form.VTypes, {
"age": function(_v) {
if (/^\d+$/.test(_v)) {
var _age = parseInt(_v);
if ((_age > 0) && (_age < 200)) return true;
}
return false;
},
"ageText": "年齡必須在0到200之間",
"ageMask": /[0-9]/i
});
Ext.onReady(function() {
new PersonListGridPanel();
});
</script>
代碼很簡(jiǎn)潔,也很清晰。只需要?jiǎng)?chuàng)建一個(gè)PersonListGridPanel即可,因?yàn)樗陨戆诵略?、修改的窗體對(duì)象,而新增和修改窗體中都使用到了負(fù)責(zé)數(shù)據(jù)編輯的PersonInfoFormPanel。
在PersonInfoFormPanel中使用了VTypes進(jìn)行數(shù)據(jù)驗(yàn)證。
新增和修改窗體僅僅是界面,負(fù)責(zé)將用戶(hù)在PersonInfoFormPanel中填寫(xiě)的數(shù)據(jù)傳回到ListGrid中以便保存,或是將ListGrid中的數(shù)據(jù)傳遞到PersonInfoFormPanel中進(jìn)行呈現(xiàn),供用戶(hù)編輯。
相關(guān)文章
學(xué)習(xí)YUI.Ext第七日-View&JSONView Part Two-一個(gè)畫(huà)室網(wǎng)站的案例
這篇文章主要介紹了學(xué)習(xí)YUI.Ext第七日-View&JSONView Part Two-一個(gè)畫(huà)室網(wǎng)站的案例2007-03-03
Ext面向?qū)ο箝_(kāi)發(fā)實(shí)踐(續(xù))
我的上一篇文章《Ext面向?qū)ο箝_(kāi)發(fā)實(shí)踐》中簡(jiǎn)述了如何編寫(xiě)一個(gè)面向?qū)ο蟮臄?shù)據(jù)維護(hù)小程序,但這一些都是基于一個(gè)客戶(hù)端數(shù)據(jù),即用戶(hù)一旦刷新頁(yè)面,所有的操作都將丟失,現(xiàn)在我們就接著上一篇文章來(lái)繼續(xù)講一下如何對(duì)數(shù)據(jù)表進(jìn)行增、刪、改、查操作。2008-11-11
學(xué)習(xí)YUI.Ext第五日--做拖放Darg&Drop
學(xué)習(xí)YUI.Ext第五日--做拖放Darg&Drop...2007-03-03
學(xué)習(xí)YUI.Ext 第四天--對(duì)話(huà)框Dialog的使用
學(xué)習(xí)YUI.Ext 第四天--對(duì)話(huà)框Dialog的使用...2007-03-03
Javascript YUI 讀碼日記之 YAHOO.util.Dom - Part.2 0
繼續(xù)在 YAHOO.util.Dom 中徘徊。由于 YAHOO.util.Dom 多次調(diào)用 batch 方法,所以先看看這個(gè)函數(shù)是怎么寫(xiě)的。有關(guān) batch 的用法,可以參見(jiàn)這里,相關(guān)的代碼如下2008-03-03

