跟我一起学extjs5(23--模块Form的自定义的设计[1])
下面开始设计和完成一个简单的Form的自定义过程。先准备数据,在ModuleModel.js中的data属性下面,加入自定义Form的参数定义,下面的代码中定义了一个新的属性tf_formSchemes,在这个属性下面可以定义多个formScheme,下面的例子中只加入了一个,在formScheme上,加了二个fieldSet,然后在fieldSet下面定义了若干个字段。
// 模块的form方案,可以定义多个方案
tf_formSchemes : [{
tf_schemeOrder : 10,
tf_schemeName : 'form方案1', // 第一个form方案
tf_windowWidth : 600, // form window 的宽度
tf_windowHeight : -1, // 高度-1 即为自动适应高度
// 表头分组
tf_schemeGroups : [{
tf_formGroupId : 1, // id号
tf_formGroupOrder : 10, // 表头分组序号
tf_formGroupName : '工程项目基本信息',
tf_numCols : 1, // 分栏数
// 每一个表头分组下面的字段
tf_groupFields : [{
tf_formFieldOrder : 5,
tf_fieldId : 10100010,
tf_colspan : 1, // 此字段占用的栏数
tf_width : -1,// 宽度,设置-1为 100%
tf_isEndRow : true
// 结束本行,下个字段从新的一行开始排列
}, {
tf_formFieldOrder : 10,
tf_fieldId : 10100020, // 工程项目名称字段
tf_colspan : 1, // 此字段占用的栏数
tf_width : -1,// 宽度,设置-1为 100%
tf_isEndRow : true
// 结束本行,下个字段从新的一行开始排列
}, {
tf_formFieldOrder : 20,
tf_fieldId : 10100030, // 工程项目编码字段
tf_colspan : 1, // 此字段占用的栏数
tf_width : -1,// 宽度,设置-1为 100%
tf_isEndRow : true
// 结束本行,下个字段从新的一行开始排列
}]
}, {
tf_formGroupOrder : 20, // 表头分组序号
tf_formGroupName : '工程项目附加信息',
tf_numCols : 2, // 分栏数
tf_collapsible : true, // 此fieldSet可折叠
tf_collapsed : false, // 默认不折叠
// 每一个表头分组下面的字段
tf_groupFields : [{
tf_formFieldOrder : 10,
tf_fieldId : 10100040
// 建筑面积
}, {
tf_formFieldOrder : 20,
tf_fieldId : 10100050
// 投资总额
}, {
tf_formFieldOrder : 30,
tf_fieldId : 10100060,
tf_isEndRow : true
// 结束本行,下个字段从新的一行开始排列
// 容积率
}, {
tf_formFieldOrder : 40,
tf_fieldId : 10100070
// 计划开工时间
}, {
tf_formFieldOrder : 50,
tf_fieldId : 10100080
// 计划竣工时间
}, {
tf_formFieldOrder : 60,
tf_fieldId : 10100090
// 是否通过验收
}, {
tf_formFieldOrder : 70,
tf_fieldId : 10100100
// 工程方量
}]
}]
}]
基础数据准备就绪,就需要创建window了。在module目录下创建一个新的目录window,在 window目录下建立文件BaseWindow.js。
/**
*
* 一个显示、修改、新增的的窗口基类
*
*/
Ext.define('app.view.module.window.BaseWindow', {
extend : 'Ext.window.Window',
alias : 'widget.basewindow',
uses : ['app.view.module.form.BaseForm'],
layout : 'fit',
maximizable : true,
closeAction : 'hide',
bodyStyle : 'padding : 2px 2px 0',
shadowOffset : 30,
layout : 'fit',
initComponent : function() {
this.maxHeight = document.body.clientHeight * 0.98;
var me = this;
this.formScheme = this.getViewModel().get('tf_formSchemes')[0]; // 取得第一个form方案
console.log(this.formScheme);
this.title = this.getViewModel().get('tf_title');
this.glyph = this.getViewModel().get('tf_glyph');
var w = this.formScheme.tf_windowWidth;
var h = this.formScheme.tf_windowHeight;
// 高度为-1表示是自适应
if (w == -1 && h == -1) {
this.width = 600;
this.height = 400;
this.maximized = true;
} else {
if (w != -1)
this.width = Math.min(w, document.body.clientWidth - 2);
if (h != -1)
this.height = Math.min(h, document.body.clientHeight - 2);
};
if (w == -1 && h != -1) { // 宽度最大化
this.width = document.body.clientWidth - 40;
}
this.tools = [{
type : 'collapse',
tooltip : '当前记录导出至Excel'
}];
this.items = [{
xtype : 'baseform',
viewModel : this.getViewModel(),
formScheme : this.formScheme
}]
this.callParent(arguments);
}
});
在这个window中根据,配置信息来创建立窗口的大小和title值,然后去创建form。
在module目录中再建立一个form目录,在form目录下建立文件BaseForm.js。在Form中设置好参数后,根据配置信息来创建各个fieldSet。这个类的处理很复杂,要处理正常的fieldSet,还要处理tab ,accordion,以及是否是子模块的Grid的判断,下面的程序里已经简化了。
/**
*
* 一个form窗口的基类,新增、显示、修改、审核、审批等功能继承了这个窗口
*
*/
Ext.define('app.view.module.form.BaseForm', {
extend : 'Ext.form.Panel',
alias : 'widget.baseform',
autoScroll : true,
buttonAlign : 'center',
initComponent : function() {
var me = this;
this.buttons = [];
this.buttons.push({
text : '关闭',
itemId : 'close',
icon : 'images/button/return.png'
});
me.items = [];
var groups = this.formScheme.tf_schemeGroups, hasTab = false;
var hasInTabPanel = false; // 是否有嵌在页里面的tab,
var inTabPanel;
Ext.each(groups, function(group) {
group.tf_numCols = group.tf_numCols || me.formScheme.tf_numCols;
hasTab = hasTab || (group.tf_displayMode == 'tab');
hasInTabPanel = hasInTabPanel
|| (group.tf_displayMode == 'intabpanel');
});
if (hasTab) {
var tabpanel = {
xtype : 'tabpanel',
frame : false,
border : false,
bodyPadding : '5 5 5 5',
items : []
};
groups[0].tf_displayMode = 'tab'; // 如果第一个tab忘了设置
var nowtab;
Ext.each(groups, function(group) {
if (group.tf_displayMode == 'tab') {
if (nowtab)
tabpanel.items.push(nowtab);
nowtab = {
xtype : 'container',
title : group.tf_formGroupName,
items : []
};
}
nowtab.items.push(me.createFieldSetOrSubModule(group));
});
tabpanel.items.push(nowtab);
me.items = tabpanel;
} else {
me.bodyStyle = 'padding : 5px 5px 0';
Ext.each(groups, function(group) {
if (group.tf_displayMode == 'intabpanel') {
inTabPanel = {
xtype : 'tabpanel',
frame : false,
border : false,
height : 400,
items : []
};
Ext.apply(inTabPanel, me
.getOtherSetting(group.tf_otherSetting))
me.items.push(inTabPanel);
} else if (group.tf_displayMode == 'intab') {
var t = me.createFieldSetOrSubModule(group);
t.title = group.tf_formGroupName;
inTabPanel.items.push(t)
} else
me.items.push(me.createFieldSetOrSubModule(group))
})
}
me.callParent(arguments);
},
getOtherSetting : function(str) {
if (!str)
return {}
else
return Ext.decode('{' + str + '}', true)
},
createFieldSetOrSubModule : function(group) {
var me = this;
return Ext.create('app.view.module.form.FieldSet', {
autoScroll : true,
viewModel : this.getViewModel(),
schemeGroup : group,
numCols : group.tf_numCols
})
},
initForm : function() {
},
// 不是grid中调用的显示某条记录的信息,可能是其他模块点击namefields来调用的
setRecordId : function(id) {
var me = this;
this.module.model.load(id, {
success : function(record, operation, success) {
// success中的record中返回的raw 数据,是字符串,没有经过decode,要自己转成对象
me.setData(Ext.create(me.module.model, Ext.decode(record.raw)));
}
});
},
setData : function(model) {
this.data = model;
// this.getForm().reset();
if (this.data) {
// Ext.suspendLayouts();
this.getForm().loadRecord(this.data);
// Ext.resumeLayouts(true);
} else
this.getForm().reset();
// 检查form中是否有子模块,如果有则刷新
}
});
Form的控件创建好以后,会继续创建每一个FieldSet的内容。在form目录中加入文件FieldSet.js。在这个FieldSet中,暂时还没有加入字段的生成。
/**
*
* 生成form中的一个fieldSet的类
*
*/
Ext.define('app.view.module.form.FieldSet', {
extend : 'Ext.form.FieldSet',
alias : 'widget.formfieldset',
defaultType : 'textfield',
defaults : {},
layout : 'anchor',
config : {
module : undefined, // 此模块的module定义
schemeGroup : undefined, // 定义了此fieldSet的属性以及下面需要加的字段
numCols : undefined,
formtype : undefined
},
initComponent : function() {
this.title = this.schemeGroup.tf_formGroupName;
this.collapsible = this.schemeGroup.tf_collapsible;
this.collapsed = this.schemeGroup.tf_collapsed;
this.items = [];
this.callParent(arguments);
}
})
以过以上步骤,加入了 window-form-fieldset的三级控件的创建,下面来显示一下结果。在GridToolbar.js中,给修改按钮加个事件:
{
text : '修改',
glyph : 0xf044,
itemId : 'edit',
handler : 'editRecord'
}
在ModuleController.js中加入函数:
editRecord : function(button) {
var window = Ext.widget('basewindow',{
viewModel : this.getView().getViewModel()
});
window.show();
},
在Module.js 的uses 中加入
'app.view.module.window.BaseWindow',这样就可以运行了。
下面一节将会加入不同种类的field。