本专题作为开发笔记持续更新,记录遇到的各种坑以备查。
2010/5/16:
Context: 以上一篇随笔中的Grid为例。例如,有两个Grid,一个是主类别,一个是子类型,分别定义在独立的另外两个文件中。另外有一个init.js用来组装这两个grid,可以这样:
代码
Ext.onReady(function() {
var RankDefGrid = new YC.RankDef.Grid();
var grid = new YC.Major.Grid();
//直接量在new完grid之后再赋值没有问题。
grid.region = "west";
grid.width = 300;
//尝试过直接修改store.url属性。但request的时候依然是原来的url。跟踪源码,发现应该如下设置。
RankDefGrid.store.proxy.api["read"].url = "/RankDef/GetByRefEntityIdWithPaging";
grid.sm = new Ext.grid.CheckboxSelectionModel({
singleSelect : true,
listeners : {
'rowselect' : function(sm, rowIndex, r) {
var id = sm.getSelected().get("Id");
if (RefConfigTab.getActiveTab().getId() == "Major_RankDef_ConfigPanel") {
RankDefGrid.store.removeAll();
RankDefGrid.store.baseParams["Id"] = grid.getSelectionModel()
.getSelected().get("Id");
RankDefGrid.store.baseParams["refEntityName"] = "Major";
RankDefGrid.store.load({
params : {
start : 0,
limit : ALL_PAGESIZE_SETTING
}
});
}
},
'rowdeselect' : function(sm, rowIndex, r) {
RankDefGrid.store.removeAll();
}
}
});
//重设了sm。对应的,cm起始需要更改。所以把原来grid的initComponent方法中的原代码:
//this.sm = new Ext.grid.CheckboxSelectionModel();改成:
//this.sm = (this.sm) ? this.sm : new Ext.grid.CheckboxSelectionModel();并重新
//调用initComponent方法。
grid.initComponent();
RankDefGrid.buildFormButtons = function() {
var btnSubmit = new Ext.ux.SubmitBtn({
handler : function() {
var form = this.win.items.items[0];
if (form.getForm().isValid()) {
form.getForm().submit({
url : '/RankDef/SaveOrUpdate',
params : {
'Id' : (form.updateEdit) ? form.entityId : "",
'Major':grid.getSelectionModel().getSelected().get("Id")
},
success : function(form, action) {
RankDefGrid.store.setDefaultSort(
'Value', 'ASC');
RankDefGrid.store.load({
params : {
start : 0,
limit : ALL_PAGESIZE_SETTING
}
});
RankDefGrid.win.destroy();
},
failure : function(form, action) {
JsHelper
.ShowError(action.result.msg);
}
});
}
},
//scope 在这里没用...不知道为什么,所以把上面handler中的原来的"this"都改成了直接引用“RankDefGrid”
scope: RankDefGrid
});
var btnCancel = new Ext.ux.CancelBtn({
handler : function() {
this.win.destroy();
},
scope : RankDefGrid
});
return [btnSubmit, btnCancel];
};
//应用sequence来添加赋值逻辑。
Ext.sequence(RankDefGrid, 'showEditFormWinFn', function() {
var form = RankDefGrid.win.items.items[0];
var theMajor = form.form.findField("MajorText");
theMajor.setValue(grid.getSelectionModel().getSelected().get("Name"));
});
var RefConfigTab = new Ext.TabPanel({
id : "Major_RefConfigTab",
frame : true,
border : true,
region : "center",
autoScroll : true,
enableTabScroll : true,
activeTab : 0,
items : [new Ext.Panel({
id : 'Major_RankDef_ConfigPanel',
title : '级别定义',
autoScroll : true,
layout : 'fit',
border : false,
items : [RankDefGrid],
listeners : {
'activate' : function(p) {
if (grid.getSelectionModel().getSelected()) {
RankDefGrid.store.removeAll();
RankDefGrid.store.baseParams["Id"] = grid.sm
.getSelected().get("Id");
RankDefGrid.store.baseParams["refEntityName"] = "Major";
RankDefGrid.store.load({
params : {
start : 0,
limit : ALL_PAGESIZE_SETTING
}
});
}
// }
}
}
})]
});
var main = new Ext.Panel({
border : false,
layout : 'border',
items : [grid, RefConfigTab]
});
JsHelper.ExtTabDoLayout(main);
grid.store.load({
params : {
start : 0,
limit : ALL_PAGESIZE_SETTING
}
});
});
var RankDefGrid = new YC.RankDef.Grid();
var grid = new YC.Major.Grid();
//直接量在new完grid之后再赋值没有问题。
grid.region = "west";
grid.width = 300;
//尝试过直接修改store.url属性。但request的时候依然是原来的url。跟踪源码,发现应该如下设置。
RankDefGrid.store.proxy.api["read"].url = "/RankDef/GetByRefEntityIdWithPaging";
grid.sm = new Ext.grid.CheckboxSelectionModel({
singleSelect : true,
listeners : {
'rowselect' : function(sm, rowIndex, r) {
var id = sm.getSelected().get("Id");
if (RefConfigTab.getActiveTab().getId() == "Major_RankDef_ConfigPanel") {
RankDefGrid.store.removeAll();
RankDefGrid.store.baseParams["Id"] = grid.getSelectionModel()
.getSelected().get("Id");
RankDefGrid.store.baseParams["refEntityName"] = "Major";
RankDefGrid.store.load({
params : {
start : 0,
limit : ALL_PAGESIZE_SETTING
}
});
}
},
'rowdeselect' : function(sm, rowIndex, r) {
RankDefGrid.store.removeAll();
}
}
});
//重设了sm。对应的,cm起始需要更改。所以把原来grid的initComponent方法中的原代码:
//this.sm = new Ext.grid.CheckboxSelectionModel();改成:
//this.sm = (this.sm) ? this.sm : new Ext.grid.CheckboxSelectionModel();并重新
//调用initComponent方法。
grid.initComponent();
RankDefGrid.buildFormButtons = function() {
var btnSubmit = new Ext.ux.SubmitBtn({
handler : function() {
var form = this.win.items.items[0];
if (form.getForm().isValid()) {
form.getForm().submit({
url : '/RankDef/SaveOrUpdate',
params : {
'Id' : (form.updateEdit) ? form.entityId : "",
'Major':grid.getSelectionModel().getSelected().get("Id")
},
success : function(form, action) {
RankDefGrid.store.setDefaultSort(
'Value', 'ASC');
RankDefGrid.store.load({
params : {
start : 0,
limit : ALL_PAGESIZE_SETTING
}
});
RankDefGrid.win.destroy();
},
failure : function(form, action) {
JsHelper
.ShowError(action.result.msg);
}
});
}
},
//scope 在这里没用...不知道为什么,所以把上面handler中的原来的"this"都改成了直接引用“RankDefGrid”
scope: RankDefGrid
});
var btnCancel = new Ext.ux.CancelBtn({
handler : function() {
this.win.destroy();
},
scope : RankDefGrid
});
return [btnSubmit, btnCancel];
};
//应用sequence来添加赋值逻辑。
Ext.sequence(RankDefGrid, 'showEditFormWinFn', function() {
var form = RankDefGrid.win.items.items[0];
var theMajor = form.form.findField("MajorText");
theMajor.setValue(grid.getSelectionModel().getSelected().get("Name"));
});
var RefConfigTab = new Ext.TabPanel({
id : "Major_RefConfigTab",
frame : true,
border : true,
region : "center",
autoScroll : true,
enableTabScroll : true,
activeTab : 0,
items : [new Ext.Panel({
id : 'Major_RankDef_ConfigPanel',
title : '级别定义',
autoScroll : true,
layout : 'fit',
border : false,
items : [RankDefGrid],
listeners : {
'activate' : function(p) {
if (grid.getSelectionModel().getSelected()) {
RankDefGrid.store.removeAll();
RankDefGrid.store.baseParams["Id"] = grid.sm
.getSelected().get("Id");
RankDefGrid.store.baseParams["refEntityName"] = "Major";
RankDefGrid.store.load({
params : {
start : 0,
limit : ALL_PAGESIZE_SETTING
}
});
}
// }
}
}
})]
});
var main = new Ext.Panel({
border : false,
layout : 'border',
items : [grid, RefConfigTab]
});
JsHelper.ExtTabDoLayout(main);
grid.store.load({
params : {
start : 0,
limit : ALL_PAGESIZE_SETTING
}
});
});
对应的,应该对其他的grid做如下更改:
代码
Ext.ns('YC','YC.Major');
YC.Major.Grid = Ext.extend(Ext.grid.GridPanel, {
enableColumnMove : true,
stripeRows : true,
frame : true,
border: true,
layout : "fit",
loadMask : true,
initComponent: function() {
this.viewConfig = {
// add view configuration here.
};
this.store = this.buildStores()[0];
this.tbar = this.buildTopToolbar();
this.bbar = this.buildBottomToolbar();
//如果重设sm并再次执行initComponent方法,这样写就不会覆盖更改。
this.sm = (this.sm) ? this.sm : new Ext.grid.CheckboxSelectionModel();
this.cm = this.buildCm();
this.on("rowdblclick", this.onrowdblclick, this);
YC.Major.Grid.superclass.initComponent.call(this);
//如果这句放在上面基类方法调用之前,那么这句代码将无效:this.onSelectionChange方法不会被触发。
this.getSelectionModel().on('selectionchange', this.onSelectionChange, this);
},
buildSM : function() {
return new Ext.grid.CheckboxSelectionModel();
},
//Build Tool Bar
buildTopToolbar : function() {
return [
{
xtype : "tbbutton",
minWidth : 80,
ref : '../addBtn',
text : "添加项",
cls : "x-btn-text-icon",
icon : "/Content/icons/add.png",
handler : this.onAdd,
scope: this
},
"-",
{
xtype : "tbbutton",
ref : '../delBtn',
minWidth : 80,
disabled : true,
text : "删除项",
cls : "x-btn-text-icon",
icon : "/Content/icons/delete.png",
handler : this.onDelete,
scope : this
},
"-",
{
xtype : "tbbutton",
minWidth : 80,
text : "双击修改项",
cls : "x-btn-text-icon",
icon : "/Content/icons/pencil.png",
disabled : true
}
];
},
buildBottomToolbar : function() {
return new Ext.PagingToolbar({
displayInfo : true,
emptyMsg : "没有数据显示",
displayMsg : "显示从{0}条数据到{1}条数据,共{2}条数据",
store : this.store,
pageSize : ALL_PAGESIZE_SETTING,
plugins : [this.filters]
});
},
//CURD handlers
onAdd : function(btn, e) {
this.showEditFormWinFn(this.store.reader, "添加专业");
},
onDelete : function(btn, e) {
JsHelper.DelConfirm(function(btn) {
if (btn == 'yes') {
// gridEditor.stopEditing();
var s = this
.getSelectionModel()
.getSelections();
for (var i = 0, r; r = s[i]; i++) {
this.store.remove(r);
}
}
});
},
onrowdblclick : function(g, rowIndex, e) {
var store = g.getStore();
var id = store.getAt(rowIndex).get("Id");
this.showEditFormWinFn(this.store.reader, "修改专业", id);
},
onSelectionChange : function(sm) {
this.delBtn.setDisabled(sm.getCount() < 1);
},
//Grid Filters
filters : new Ext.ux.grid.GridFilters({
encode : true,
filters : [{type: 'string',dataIndex: 'Name'},
{type: 'date',dataIndex: 'CreateTime'},
{type: 'boolean',dataIndex: 'IsDelete'},
{type: 'string',dataIndex: 'Id'}]
}),
//Stores. Add additional stores in this function.
buildStores : function() {
var store = new Ext.data.Store({
url : "/Major/GetPlist",
remoteSort : true,
reader : new Ext.data.JsonReader({
root : 'data',
totalProperty : 'total',
id : 'Id'
}, [
{name: 'Name',type: 'string'},
{name: 'CreateTime',type: 'date'},
{name: 'IsDelete',type: 'boolean'},
{name: 'Id',type: 'string'}
])
});
store.on('remove', this.onStoreRemove, this);
store.setDefaultSort('Name', 'ASC');
return [store];
},
onStoreRemove : function(thiz, record, index) {
Ext.Ajax.request({
url : '/Major/Delete',
params : {
'Id' : record.data.Id
},
success : function(response, opts) {
var result = Ext.util.JSON
.decode(response.responseText);
if (result.success == false) {
JsHelper.ShowError(result.msg);
this.store.insert(0, record);
}
}
});
},
//Build the popup win.
//必须在new FormPanel的时候就设置formReader。如果new完了在用例如form.reader = formReader的方式将会无效,症状是值不会赋给datafield.
buildWin : function(formReader) {
var form = new Ext.FormPanel({
id : 'mainForm',
border : false,
waitMsgTarget : true,
labelWidth : 90,
frame : true,
reader : formReader,
bodyStyle : 'padding:5px 5px 0',
labelAlign : 'right',
layout : 'tableform',
layoutConfig : {
columns : 2
},
defaultType: 'textfield',
defaults: {
allowBlank: false,
150
},
items : [{name: 'Name',xtype: 'textfield', fieldLabel : '专业名称'}],
buttonAlign : 'center',
buttons : this.buildFormButtons()
});
var win = new Ext.Window({
iconCls : 'application_form',
width : 700,
resizable : false,
constrain : true,
autoHeight : true,
modal : true,
closeAction : 'close',
plain : true,
items : [form]
});
return win;
},
buildFormButtons : function() {
var btnSubmit = new Ext.ux.SubmitBtn({
handler : function() {
var form = this.win.items.items[0];
if (form.getForm().isValid()) {
form.getForm().submit({
url : '/Major/SaveOrUpdate',
params : {
'Id' : (form.updateEdit) ? form.entityId : ""
},
success : function(form, action) {
this.store.setDefaultSort(
'Name', 'ASC');
this.store.load({
params : {
start : 0,
limit : ALL_PAGESIZE_SETTING
}
});
this.win.destroy();
},
failure : function(form, action) {
JsHelper
.ShowError(action.result.msg);
}
});
}
},
scope: this
});
var btnCancel = new Ext.ux.CancelBtn({
handler : function() {
this.win.destroy();
},
scope : this
});
return [btnSubmit, btnCancel];
},
showEditFormWinFn : function(formReader, title, id) {
this.win = this.buildWin(formReader);
var updateEdit = Ext.isDefined(id);
var formLoadArgs = (updateEdit) ? {
url : '/Major/Get',
params : {
'Id' : id
},
waitMsg : '数据加载中...'
} : null;
var form = this.win.items.items[0];
form.reader = formReader;
form.updateEdit = updateEdit;
form.entityId = id;
this.win.title = title;
this.win.show();
if (formLoadArgs) {
form.load(formLoadArgs);
}
},
//Build the grid ColumnModel
buildCm : function() {
return new Ext.grid.ColumnModel([new Ext.grid.RowNumberer(), this.sm,
{header: '专业名称',dataIndex: 'Name',sortable: true},
{header: '创建时间',dataIndex: 'CreateTime',sortable: true}
]);
}
});
Ext.reg("ycmajorgrid", YC.Major.Grid);
Ext.ns('YC','YC.Major');
YC.Major.Grid = Ext.extend(Ext.grid.GridPanel, {
enableColumnMove : true,
stripeRows : true,
frame : true,
border: true,
layout : "fit",
loadMask : true,
initComponent: function() {
this.viewConfig = {
// add view configuration here.
};
this.store = this.buildStores()[0];
this.tbar = this.buildTopToolbar();
this.bbar = this.buildBottomToolbar();
//如果重设sm并再次执行initComponent方法,这样写就不会覆盖更改。
this.sm = (this.sm) ? this.sm : new Ext.grid.CheckboxSelectionModel();
this.cm = this.buildCm();
this.on("rowdblclick", this.onrowdblclick, this);
YC.Major.Grid.superclass.initComponent.call(this);
//如果这句放在上面基类方法调用之前,那么这句代码将无效:this.onSelectionChange方法不会被触发。
this.getSelectionModel().on('selectionchange', this.onSelectionChange, this);
},
buildSM : function() {
return new Ext.grid.CheckboxSelectionModel();
},
//Build Tool Bar
buildTopToolbar : function() {
return [
{
xtype : "tbbutton",
minWidth : 80,
ref : '../addBtn',
text : "添加项",
cls : "x-btn-text-icon",
icon : "/Content/icons/add.png",
handler : this.onAdd,
scope: this
},
"-",
{
xtype : "tbbutton",
ref : '../delBtn',
minWidth : 80,
disabled : true,
text : "删除项",
cls : "x-btn-text-icon",
icon : "/Content/icons/delete.png",
handler : this.onDelete,
scope : this
},
"-",
{
xtype : "tbbutton",
minWidth : 80,
text : "双击修改项",
cls : "x-btn-text-icon",
icon : "/Content/icons/pencil.png",
disabled : true
}
];
},
buildBottomToolbar : function() {
return new Ext.PagingToolbar({
displayInfo : true,
emptyMsg : "没有数据显示",
displayMsg : "显示从{0}条数据到{1}条数据,共{2}条数据",
store : this.store,
pageSize : ALL_PAGESIZE_SETTING,
plugins : [this.filters]
});
},
//CURD handlers
onAdd : function(btn, e) {
this.showEditFormWinFn(this.store.reader, "添加专业");
},
onDelete : function(btn, e) {
JsHelper.DelConfirm(function(btn) {
if (btn == 'yes') {
// gridEditor.stopEditing();
var s = this
.getSelectionModel()
.getSelections();
for (var i = 0, r; r = s[i]; i++) {
this.store.remove(r);
}
}
});
},
onrowdblclick : function(g, rowIndex, e) {
var store = g.getStore();
var id = store.getAt(rowIndex).get("Id");
this.showEditFormWinFn(this.store.reader, "修改专业", id);
},
onSelectionChange : function(sm) {
this.delBtn.setDisabled(sm.getCount() < 1);
},
//Grid Filters
filters : new Ext.ux.grid.GridFilters({
encode : true,
filters : [{type: 'string',dataIndex: 'Name'},
{type: 'date',dataIndex: 'CreateTime'},
{type: 'boolean',dataIndex: 'IsDelete'},
{type: 'string',dataIndex: 'Id'}]
}),
//Stores. Add additional stores in this function.
buildStores : function() {
var store = new Ext.data.Store({
url : "/Major/GetPlist",
remoteSort : true,
reader : new Ext.data.JsonReader({
root : 'data',
totalProperty : 'total',
id : 'Id'
}, [
{name: 'Name',type: 'string'},
{name: 'CreateTime',type: 'date'},
{name: 'IsDelete',type: 'boolean'},
{name: 'Id',type: 'string'}
])
});
store.on('remove', this.onStoreRemove, this);
store.setDefaultSort('Name', 'ASC');
return [store];
},
onStoreRemove : function(thiz, record, index) {
Ext.Ajax.request({
url : '/Major/Delete',
params : {
'Id' : record.data.Id
},
success : function(response, opts) {
var result = Ext.util.JSON
.decode(response.responseText);
if (result.success == false) {
JsHelper.ShowError(result.msg);
this.store.insert(0, record);
}
}
});
},
//Build the popup win.
//必须在new FormPanel的时候就设置formReader。如果new完了在用例如form.reader = formReader的方式将会无效,症状是值不会赋给datafield.
buildWin : function(formReader) {
var form = new Ext.FormPanel({
id : 'mainForm',
border : false,
waitMsgTarget : true,
labelWidth : 90,
frame : true,
reader : formReader,
bodyStyle : 'padding:5px 5px 0',
labelAlign : 'right',
layout : 'tableform',
layoutConfig : {
columns : 2
},
defaultType: 'textfield',
defaults: {
allowBlank: false,
150
},
items : [{name: 'Name',xtype: 'textfield', fieldLabel : '专业名称'}],
buttonAlign : 'center',
buttons : this.buildFormButtons()
});
var win = new Ext.Window({
iconCls : 'application_form',
width : 700,
resizable : false,
constrain : true,
autoHeight : true,
modal : true,
closeAction : 'close',
plain : true,
items : [form]
});
return win;
},
buildFormButtons : function() {
var btnSubmit = new Ext.ux.SubmitBtn({
handler : function() {
var form = this.win.items.items[0];
if (form.getForm().isValid()) {
form.getForm().submit({
url : '/Major/SaveOrUpdate',
params : {
'Id' : (form.updateEdit) ? form.entityId : ""
},
success : function(form, action) {
this.store.setDefaultSort(
'Name', 'ASC');
this.store.load({
params : {
start : 0,
limit : ALL_PAGESIZE_SETTING
}
});
this.win.destroy();
},
failure : function(form, action) {
JsHelper
.ShowError(action.result.msg);
}
});
}
},
scope: this
});
var btnCancel = new Ext.ux.CancelBtn({
handler : function() {
this.win.destroy();
},
scope : this
});
return [btnSubmit, btnCancel];
},
showEditFormWinFn : function(formReader, title, id) {
this.win = this.buildWin(formReader);
var updateEdit = Ext.isDefined(id);
var formLoadArgs = (updateEdit) ? {
url : '/Major/Get',
params : {
'Id' : id
},
waitMsg : '数据加载中...'
} : null;
var form = this.win.items.items[0];
form.reader = formReader;
form.updateEdit = updateEdit;
form.entityId = id;
this.win.title = title;
this.win.show();
if (formLoadArgs) {
form.load(formLoadArgs);
}
},
//Build the grid ColumnModel
buildCm : function() {
return new Ext.grid.ColumnModel([new Ext.grid.RowNumberer(), this.sm,
{header: '专业名称',dataIndex: 'Name',sortable: true},
{header: '创建时间',dataIndex: 'CreateTime',sortable: true}
]);
}
});
Ext.reg("ycmajorgrid", YC.Major.Grid);
注意注释。