This is a sample program I wrote one by one while learning Ext. It is just for practice and does not have full functions. I will record it in my blog now and hope to share it with my friends who are learning Ext
Brief description of the sample program:
This Demo is to demonstrate how to use GridPanel to display data, add toolbar buttons to GridPanel, and provide pop-up forms to add data.
Ext components used
This demo involves the three components of GridPanel, FormPanel and Window in Ext.
Rendering
Now let’s start explaining the code, first look at the code snippet to create GridPanel
//Define the data list panel class
PersonListGridPanel = Ext.extend(Ext.grid.GridPanel, {
insertWin: null,
updateWin: null,
constructor: function() {
//Add custom event
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); //Trigger custom event
} ,
scope: this
}
}
}),
store: new Ext.data.JsonStore({
data: [{name: "李宗胜", age: 28 , sex: "male"}, {name: "林伊伦", age: 26, sex: "female"}],
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: "Here is the prompt information"},
{header: "Sex", width: 100, sortable: true, dataIndex: "sex", align: "center"}
]),
tbar: [{
text: "Add person",
handler: function() {
//********************** *******************************
//If the Close method of InsertPersonInfoWindow is not overridden
//Before calling Need to check whether its instance insertWin is released
//Usage example:
//if (!this.insertWin) {
// this.insertWin = new InsertPersonInfoWindow();
//}
//this.insertWin.show();
//********************************** ******************
this.insertWin.show();
},
scope: this
}, "-", {
text: "Modifier",
handler: function() {
var r = this.getActiveRecord();
if (!r) return;
//definitely The Show method must be called first, and then the Load method,
//Otherwise the data will not be presented
this.updateWin.show();
this.updateWin.load(r);
},
scope: this
}, "-", {
text: "Delete Person",
handler: function() {
var r = this.getActiveRecord();
if (!r) return;
Ext.MessageBox.confirm("Delete", "Delete current personnel information? ", function(btn) {
if(btn == "yes") {
this.delRecord(r);
}
}, this);
},
scope: this
}]
});
},
getActiveRecord: function() {
var sm = this.getSelectionModel();
//When there is no selected record , does it throw an exception or return 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') ;
}
});
Data maintenance panel code
//Define the data maintenance panel, which will be used in the new and modified forms defined later
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", //Note that the name attribute is used here instead of id, because PersonInfoFormPanel will be used by adding and inserting two forms. There will be a conflict in using the id, resulting in the component not being displayed correctly.
fieldLabel: "Name",
allowBlank: false,
emptyText: "Please enter your name" ,
blankText: "Name cannot be empty"
}, {
name: "age",
fieldLabel: "Age",
vtype: "age"
}, {
hiddenName: "sex",
xtype: "combo",
fieldLabel: "Sex",
store: new Ext.data.SimpleStore({
fields: [
{name: 'Sex'}
],
data:[["male"], ["female"]]
}),
mode: 'local',
displayField:'Sex',
triggerAction: 'all',
emptyText:'Select gender...'
}]
})
},
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();
}
});
maintenance of data From a design perspective, the two actions of adding and updating require writing two forms to operate them. Careful friends will definitely think that the new and updated actions are for the same data table, so can you just write one form and then reuse it? The answer is yes. Next we will first write a form base class.
//Newly added, modify the form base class
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, //Modal form
onEsc: Ext. emptyFn,
closeAction: "hide",
items: [this.form],
buttons: [{
text: "OK",
handler: this.onSubmitClick,
scope: this
}, {
text: "Cancel",
handler: this.onCancelClick,
scope: this
}]
});
//alert (this.onSubmitClick);
},
close: function() {
//Need to override the CLose method,
//Otherwise the entity will be released when the form is closed
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();
}
});
After the base class is written, we can use the inherited method to write new and updated forms.
//Define the new data form
InsertPersonInfoWindow = Ext.extend(PersonInfoWindow, {
title: "Add"
});
//============================================== ================================
//Define the edit data form
UpdatePersonInfoWindow = Ext.extend(PersonInfoWindow, {
title: "Modify",
load: function(r) {
this.form.setValues(r);
}
}) ;
In order to distinguish between new and updated forms, we specify the Title attribute for them in their respective implementation classes. In addition, we need to add another method for loading the data to be edited in the updated form class. Load.
The script part is complete, let’s see how to use it in HTML. Reference code in HTML
The code is very concise and clear. You only need to create a PersonListGridPanel, because it contains new and modified form objects, and the new and modified forms use the PersonInfoFormPanel responsible for data editing.
VTypes are used in PersonInfoFormPanel for data validation.
New and modified forms are just interfaces, responsible for transferring the data filled in by the user in the PersonInfoFormPanel back to the ListGrid for saving, or transferring the data in the ListGrid to the PersonInfoFormPanel for presentation for the user to edit.
Attach the complete HTML code and JavaScript code files.
Grid.html
PersonListGridPanel.js
//Define the data list panel class
PersonListGridPanel = Ext.extend(Ext.grid.GridPanel, {
insertWin: null,
updateWin: null,
constructor: function( ) {
//Add custom events
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); //Trigger custom events
},
scope: this
}
}
}),
store: new Ext.data.JsonStore({
data: [{name: "李宗胜", age: 28, sex: "male"}, {name: "林伊伦", age: 26, sex: "female"}],
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: "Here is the prompt information"},
{header: "Sex", width: 100, sortable: true, dataIndex: "sex", align : "center"}
]),
tbar: [{
name: "btnFirst",
//text: "First",
iconCls: "x-tbar-page- first",
handler: function () {
this.getSelectionModel().selectFirstRow();
},
scope: this
}, {
name: "btnPrev" ,
//text: "Prev",
iconCls: "x-tbar-page-prev",
handler: function () {
this.getSelectionModel().selectPrevious();
},
scope: this
}, {
name: "btnNext",
//text: "Next",
iconCls: "x-tbar-page-next" ,
handler: function () {
this.getSelectionModel().selectNext();
},
scope: this
}, {
name: "btnLast",
//text: "Last",
iconCls: "x-tbar-page-last",
handler: function () {
this.getSelectionModel().selectLastRow();
},
scope: this
}, "-", {
text: "Add",
handler: function() {
//******** ******************************************
//If there is no heavy Write the Close method of InsertPersonInfoWindow
//Before calling, you need to check whether its instance insertWin has been released
//Usage example:
//if (!this.insertWin) {
// this.insertWin = new InsertPersonInfoWindow();
//}
//this.insertWin.show();
//******************** *****************************
this.insertWin.show();
},
scope: this
}, "-", {
text: "Modify",
handler: function() {
var r = this.getActiveRecord();
if (!r ) return;
//How to fill data into the form?
this.updateWin.show();
this.updateWin.load(r);
} ,
scope: this
}, "-", {
text: "Delete",
handler: function() {
var r = this.getActiveRecord();
if (!r) return;
Ext.MessageBox.confirm("Delete", "Delete current personnel information? ", function(btn) {
if(btn == "yes") {
this.delRecord(r);
}
}, this);
},
scope: this
}]
});
},
getActiveRecord: function() {
var sm = this.getSelectionModel();
//When there is no selected record , does it throw an exception or return 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') ;
}
});
//================================ ===============================================
//Define the data maintenance panel, which will be used in the new and modified forms defined later
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", //Note that the name attribute is used here instead of id, because PersonInfoFormPanel will be used by adding and inserting two forms. Using id will conflict, causing the component to not be displayed correctly
fieldLabel: "Name ",
allowBlank: false,
emptyText: "Please enter your name",
blankText: "The name cannot be empty"
}, {
name: "age",
fieldLabel : "Age",
vtype: "age"
}, {
hiddenName: "sex",
xtype: "combo",
fieldLabel: "Sex",
store: new Ext.data.SimpleStore({
fields: [
{name: 'Sex'}
],
data:[["male"], ["female"] ]
}),
mode: 'local',
displayField:'Sex',
triggerAction: 'all',
emptyText: 'Select gender...'
} ]
})
},
getValues: function() {
if (this.getForm().isValid()) {
return new Ext.data.Record(this.getForm ().getValues());
}
else {
throw Error("Incomplete information");
}
},
setValues: function(r) {
//alert(Ext.util.JSON.encode(r.data));
this.getForm().loadRecord(r);
},
reset: function() {
this.getForm().reset();
}
});
//====================== ================================================== =======
//Add and modify the form base class
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, //modal form
onEsc: Ext.emptyFn,
closeAction: "hide",
items: [this.form],
buttons: [{
text: "OK",
handler: this.onSubmitClick,
scope: this
}, {
text: "Cancel",
handler: this.onCancelClick,
scope: this
}]
}) ;
//alert(this.onSubmitClick);
},
close: function() {
//Need to override the CLose method,
//Otherwise the form will be closed The realization is released
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();
}
});
//======================================== ========================================
//Define new Add data form
InsertPersonInfoWindow = Ext.extend(PersonInfoWindow, {
title: "Add"
});
//============ ================================================== ================
//Define the edit data form
UpdatePersonInfoWindow = Ext.extend(PersonInfoWindow, {
title: "Modify",
load: function(r) {
this.form.setValues(r);
}
});