首页 > 代码库 > 跟我一起学extjs5(24--模块Form的自定义的设计[2])

跟我一起学extjs5(24--模块Form的自定义的设计[2])

跟我一起学extjs5(24--模块Form的自定义的设计[2])

        在本节中将要加入各种类型的字段,在加入字段的时候由于可以一行加入多个字段,因此层次结构又多了一层fieldcontainer。form里面的主要层次结构如下: form -- fieldSet -- fieldcontainer -- field。
        现在加入fieldcontainer的生成器的文件,在factory中加入文件FieldContainerFactory.js
/**
 * 字段容器factory
 */
Ext.define('app.view.module.factory.FieldContainerFactory', {

	statics : {

		getContainer : function(container, module, formtype) {

			var result = {
				xtype : 'fieldcontainer',
				layout : 'hbox',
				margin : '0 0 0 0',
				items : []
			};
			for (var i in container) {
				var field = container[i];
				// 如果是空的位置
				if (field.spacer) {
					result.items.push({
								xtype : 'fieldcontainer',
								layout : 'anchor',
								margin : '0 0 0 0',
								flex : field.flex
							});
				} else {
					var fieldDefine = module.getFieldDefine(field.tf_fieldId);

					var f = app.view.module.factory.FormFieldFactory.getField(fieldDefine,
							field, formtype, module);

					var c = {
						xtype : 'fieldcontainer',
						layout : (  f.moduleName )
								? (field.tf_width != -1 ? 'table' : 'hbox')
								: 'anchor',
						flex : field.tf_colspan,
						items : []
					};
					if (c.layout == 'hbox')
						c.margin = '0 0 5 0';
					c.items.push(f);

					result.items.push(c);
				}
			}
			return result;
		}
	}
});

        现在要加入最后一个field的生成器,FormFieldFactory.js,此文件敢放在factory目录之下。
/**
 * 用于生成form中的每一个field
 */

Ext.define('app.view.module.factory.FormFieldFactory', {

	statics : {
		labelDefaultWidth : 92,
		dateDefaultSize : 14,
		integerDefaultSize : 10,
		moneyDefaultSize : 14,
		/**
		 * 根据module定义,formField的定义,formtype来返回一个field的定义
		 */
		getField : function(fieldDefine, formField, formtype, module) {


			var field = {
				name : fieldDefine.tf_fieldName,
				fieldLabel : formField.fieldLabel
						|| (formField.labelAhead ? formField.labelAhead : '')
						+ fieldDefine.tf_title.replace(new RegExp('--', 'gm'), ''),
				labelAlign : formField.labelAlign || 'right',
				labelWidth : formField.labelWidth || this.labelDefaultWidth,
				behindText : formField.behindText || fieldDefine.behindText
			};
			if (field.behindText && field.behindText == ' ')
				delete field.behindText;

			if (formField.labelWidth)
				field.labelWidth = formField.labelWidth;
			if (formField.hideLabel)
				field.hideLabel = true;
			// 如果是隐藏字段
			if (this.getIsHidden(fieldDefine, formField)) {
				Ext.apply(field, {
							xtype : 'hiddenfield'
						});
				return field;
			}

			Ext.apply(field, this.getFieldXType(fieldDefine, field));
			if (formField.tf_width == -1) {
				delete field.size;
				field.anchor = '100%';
			}

			// 是否是必添字段
			if (fieldDefine.tf_isRequired)
				Ext.apply(field, {
							allowBlank : false
						});


			return field;
		},

		/**
		 * 判断字段类型
		 */
		getFieldXType : function(fieldDefine, field) {
		
				switch (fieldDefine.tf_fieldType) {
					case 'Date' :
						return {
							size : this.dateDefaultSize,
							format : 'Y-m-d',
							xtype : 'datefield',
							submitFormat : 'Y-m-d'
						}
					case 'Datetime' :
						return {
							size : this.dateDefaultSize,
							format : 'Y-m-d H:i:s',
							xtype : 'datetimefield'
						}
					case 'Boolean' :
						return {
							xtype : 'checkboxfield',
							inputValue : 'true'
						};
					case 'Integer' :
						return {
							minValue : -9999999999,
							maxValue : 9999999999,
							fieldStyle : "text-align:right",
							size : this.integerDefaultSize,
							xtype : 'numberfield',
							enableKeyEvents : true,
							listeners : {
								keydown : function(field, e, eOpts) {
									if (e.getKey() == Ext.EventObject.ENTER) {
										var f = field.nextSibling('field[readOnly=false]');
										if (!!f)
											f.focus();
										return false;
									}
								}
							}
						};
					case 'Double' :
						return {
							size : this.moneyDefaultSize,
							hideTrigger : true,
							xtype : 'numberfield',
							behindText : '元'

						};
					case 'Float' :
						return {
							minValue : -9999999999,
							maxValue : 9999999999,
							size : this.moneyDefaultSize,
							hideTrigger : true,
							xtype : 'numberfield'
						};
					case 'Percent' :
						return {
							size : this.moneyDefaultSize,
							xtype : 'numberfield',
							// behindText : '%',
							percent : true
						};
					case 'String' :
						var len = fieldDefine.l;
						if (len == 0 || len > 100)
							return {
								maxLength : len == 0 ? Number.MAX_VALUE : len,
								enforceMaxLength : true,
								anchor : '100%',
								grow : true,
								growMax : 200,
								growMin : 40,
								xtype : 'textareafield'
							}
						else
							return {
								maxLength : len,
								size : len,
								enforceMaxLength : true,
								xtype : 'textfield',
								enableKeyEvents : true,
								listeners : {
									keydown : function(field, e, eOpts) {
										if (e.getKey() == Ext.EventObject.ENTER) {
											var f = field.nextSibling('field[readOnly=false]');
											if (!!f)
												f.focus();
											return false;
										}
									}
								}
							};

				}
		},

		/**
		 * 判断是否是hidden字段
		 */
		getIsHidden : function(fieldDefine, formField) {
			return (fieldDefine.tf_isHidden || formField.tf_isHidden)
		}
	}
});

        上面的字段生成factory中省略了combo和选择父级字段属性的操作,只生成字符型,数值型,布尔型和日期型的内容。

        现在还要修改一下fieldSet.js中的内容,使其加入FieldContainer,文件重新发布一下:
/**
 * 
 * 生成form中的一个fieldSet的类
 * 
 */
Ext.define('app.view.module.form.FieldSet', {
			extend : 'Ext.form.FieldSet',
			alias : 'widget.formfieldset',

			requires : ['app.view.module.factory.FieldContainerFactory',
					'app.view.module.factory.FormFieldFactory'],

			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 = [];

				var containers = []; // 要计算一下有多少个container,如果col=2,那么二个一换行,或者指定换行
				var hiddens = []; // 隐藏的字段
				var container = [];
				var c = 0;

				for (var i in this.schemeGroup.tf_groupFields) {
					var field = this.schemeGroup.tf_groupFields[i];
					var fieldDefine = this.getViewModel()
							.getFieldDefine(field.tf_fieldId);
					// 如果是隐藏字段,那么就直接放在隐藏字段的数组里
					if (fieldDefine && fieldDefine.tf_isHidden) {
						hiddens.push(field);
						continue;
					}
				}

				for (var i in this.schemeGroup.tf_groupFields) {
					var field = this.schemeGroup.tf_groupFields[i];
					var fieldDefine = this.getViewModel()
							.getFieldDefine(field.tf_fieldId);
					if (fieldDefine && fieldDefine.tf_isHidden) {
						continue;
					}
					// 设置tf_colspan如果是0,那么置为1,如果大于tf_colspan,置为tf_colspan
					field.tf_colspan = field.tf_colspan ? field.tf_colspan : 1;
					if (field.tf_colspan > this.numCols)
						field.tf_colspan = this.numCols;
					// 如果加上这一行,超出了numCols,那么就要分二行了
					if (c + field.tf_colspan > this.numCols) {
						if (this.numCols - c > 0)
							container.push({
										spacer : true,
										flex : this.numCols - c
									});
						containers.push(container);
						container = [];
						container.push(field);
						c = field.tf_colspan;
					} else {
						container.push(field);
						c += field.tf_colspan;
						if (c >= this.numCols || field.tf_isEndRow) {
							if (this.numCols - c > 0)
								container.push({
											spacer : true,
											flex : this.numCols - c
										});
							c = 0;
							containers.push(container);
							container = [];
						}
					}
				}
				if (container.length > 0)
					containers.push(container);
				// 生成每一个container ,一个container中可以放置若干个字段,如果分栏是3,那就放3个
				for (var i in containers) {
					this.items.push(app.view.module.factory.FieldContainerFactory
							.getContainer(containers[i], this.getViewModel(), this.formtype));
				}

				// 加入隐藏的字段
				for (var i in hiddens) {
					var field = hiddens[i];
					var fieldDefine = this.module.getFieldDefine(field.tf_fieldId);
					var f = app.view.module.factory.FormFieldFactory.getField(
							fieldDefine, field, this.formtype);
					this.items.push(f);
				}

				this.callParent(arguments);
			}
		})

        BaseForm.js中也对buttons重新定义一下,加入了一个保存按钮。
				this.buttons.push({
							text : '保存',
							itemId : 'save',
							glyph : 0xf0c7
						},{
							text : '关闭',
							itemId : 'close',
							glyph : 0xf148,
							handler : function(button){
								button.up('window').hide();
							}
						});

        ModuleController.js中的editRecord事件的处理函数也修改,增加了调用当前选中Grid中记录的函数。
	editRecord : function(button) {
		var window = Ext.widget('basewindow', {
					viewModel : this.getView().getViewModel()
				});
		window.down('baseform').setData(this.getView().down('modulegrid')
				.getSelectionModel().getSelection()[0]);
		window.show();
	},

        经过以上步骤,可以看到一个修改form的窗口如下,窗口的高度是自动适应的。



        至此,一个根据form参数自定义的基本界面搭建完成了。对于简单的应用这样搭建已经足够了,对于复杂的field的配置,你可以把他描述成属性值的配置,然后再入解释执行的代码,这样你可以完成更多的定制功能。比如说现在的字段建筑面积后面的“平米”如何加入,如何加入各种类型的combo字段等等,我现在的这个讲解只提供一个自定义的思路,有更多想法还要自己去实现。