这一节加入模块自定义字段,并根据这些字段生成model。然后再定义grid中的分组和列。从这一切开始真正进入到了模块自定义的节奏当中,代码的复杂度和技巧性也大大提高。先从模块字段的自定义开始。先看一下ModuleModel.js中加入的新的定义:

/**
* 模块的数据模型
*/ Ext.define('app.view.module.ModuleModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.module', // 在开发过程中我先用设定好的值放于data中,等以后自定义的时候,data里的值都是从后台取得的
// 所有数据库里的字段,我都以tf_开头,只是为了表示这是从后台读取过来的 data: { tf_moduleId: '1010', // 模块ID号:一个数字的ID号,可以根据此ID号的顺序将相同分组的模块放在一块。
tf_ModuleGroup: '工程管理',// 模块分组:模块分到哪个组里,比如说业务模块1、业务模块2、系统设置、系统管理等。
tf_moduleName: 'Global', // 模块标识:系统中唯一的模块的标识
tf_title: '工程项目',// 模块名称:能够描述此模块信息的名称。
tf_glyph: 0xf0f7, // 图标字符值
tf_shortname: null,// 模块简称:如果名称过长,有些地方可以用简称来代替。
tf_englishName: null,// 模块英文名称:万一要制作英文版,可以用英文名称。
tf_englishShortName: null, // 模块英文简称:可以用作生成编码字段。
tf_description: null,// 模块描述:
tf_remark: null,
// 备注: // 下面还有若干字段未加入,以后用到的时候再加入
tf_primaryKey: 'tf_id', // 主键
tf_nameFields: 'tf_name', // 可用于描述记录的字段 // 此模块的自定义字段,此处先用手工定义,以后换成从数据库中自动取得
tf_fields: [{
tf_fieldId: 10100010, // 此字段的id值,所有的字段都是保存在一字段表中,这是主键值
tf_fieldName: 'tf_id',// 字段名
tf_title: '序号',// 字段描述
tf_fieldType: 'Integer', // 字段类型
tf_isHidden: true, // 是否是隐藏字段
tf_fieldGroup: '工程基本信息' // 字段分组
// 是否是隐藏字段
}, {
tf_fieldId: 10100020,
tf_fieldName: 'tf_name',
tf_title: '工程项目名称',
tf_fieldType: 'String',
tf_fieldLen: 50,
tf_isRequired: true, // 是否是必添项
tf_fieldGroup: '工程基本信息' }, {
tf_fieldId: 10100030,
tf_fieldName: 'tf_code',
tf_title: '工程项目编码',
tf_fieldType: 'String',
tf_fieldLen: 20,
tf_isRequired: true,
tf_fieldGroup: '工程基本信息' // 字段分组 }, {
tf_fieldId: 10100040, // 加入一个整型字段
tf_fieldName: 'tf_squaremeter',
tf_title: '建筑面积',
tf_fieldType: 'Integer',
tf_unitText: '平米', // 字段单位
tf_fieldGroup: '工程附加信息',
tf_allowSummary: true
// 可以对此字段进行小计
}, {
tf_fieldId: 10100050, // 加入一个金额字段
tf_fieldName: 'tf_budget',
tf_title: '投资总额',
tf_fieldType: 'Double',
tf_isMoney: true, // 此字段是一个金额字段
tf_fieldGroup: '工程附加信息',
tf_allowSummary: true
}, {
tf_fieldId: 10100060, // 加入一个百分比字段
tf_fieldName: 'tf_rjl',
tf_title: '容积率',
tf_fieldType: 'Percent',
tf_fieldGroup: '工程附加信息'
}, {
tf_fieldId: 10100070, // 加入一个日期
tf_fieldName: 'tf_startDate',
tf_title: '计划开工时间',
tf_fieldType: 'Date',
tf_fieldGroup: '工程附加信息'
}, {
tf_fieldId: 10100080, // 加入一个日期
tf_fieldName: 'tf_endDate',
tf_title: '计划竣工时间',
tf_fieldType: 'Date',
tf_fieldGroup: '工程附加信息'
}, {
tf_fieldId: 10100090, // 加入一个布尔字段
tf_fieldName: 'tf_isValid',
tf_title: '是否通过验收',
tf_fieldType: 'Boolean',
tf_fieldGroup: '工程附加信息'
}, {
tf_fieldId: 10100100, // 加入一个数值字段
tf_fieldName: 'tf_m3',
tf_title: '工程方量',
tf_fieldType: 'Double',
tf_fieldGroup: '工程附加信息'
}], // 模块的grid方案,可以定义多个方案
tf_gridSchemes: [{
tf_schemeOrder: 10,
tf_schemeName: 'Grid方案1', // 第一个grid方案
// 表头分组
tf_schemeGroups: [{
tf_gridGroupId: 1, // id号
tf_gridGroupOrder: 10, // 表头分组序号
tf_gridGroupName: '工程项目基本信息',
tf_isShowHeaderSpans: true, // 是否显示分组
tf_isLocked: true, // 是否锁定此分组
// 每一个表头分组下面的字段
tf_groupFields: [{
tf_gridFieldOrder: 10,
tf_fieldId: 10100020, // 工程项目名称字段
tf_columnWidth: 200
}, {
tf_gridFieldOrder: 20,
tf_fieldId: 10100030, // 工程项目编码字段
tf_columnWidth: 120
}]
}, {
tf_gridGroupOrder: 20, // 表头分组序号
tf_gridGroupName: '工程项目附加信息',
tf_isShowHeaderSpans: true, // 是否显示headerspan
tf_isLocked: false, // 是否锁定此分组
// 每一个表头分组下面的字段
tf_groupFields: [{
tf_gridFieldOrder: 10,
tf_fieldId: 10100040 // 建筑面积
}, {
tf_gridFieldOrder: 20,
tf_fieldId: 10100050 // 投资总额
}, {
tf_gridFieldOrder: 30,
tf_fieldId: 10100060
// 容积率
}, {
tf_gridFieldOrder: 40,
tf_fieldId: 10100070
// 计划开工时间
}, {
tf_gridFieldOrder: 50,
tf_fieldId: 10100080
// 计划竣工时间
}, {
tf_gridFieldOrder: 60,
tf_fieldId: 10100090, // 是否通过验收
tf_columnWidth: 80
}, {
tf_gridFieldOrder: 70,
tf_fieldId: 10100100
// 工程方量
}]
}] }] }, // 根据字段id,找到字段相应的定义
getFieldDefine: function (fieldId) {
var result = null;
Ext.Array.each(this.data.tf_fields, function (field) {
if (field.tf_fieldId == fieldId) {
result = field;
return false;
}
});
return result;
} })

在上面代码中在data里面加入了tf_fields这个数组,这个数组下的每个元素都是一个字段,比如:

{
tf_fieldId : 10100020,
tf_fieldName : 'tf_name',
tf_title : '工程项目名称',
tf_fieldType : 'String',
tf_fieldLen : 50,
tf_isRequired : true, // 是否是必添项
tf_fieldGroup : '工程基本信息' }

上面就定义了一个工程项目名称的字段,包括id号,字段名称,类型,长度,是否是必添项,分组信息等等。在这个工程项目模块中,我加入了各种类型的字段,有字符型,整型,浮点型,金额型,日期型,布尔型,都可以演示了看看效果。

字段定义好了以后,需要能够根据字段的定义自动生成model。下面我编了一个model工厂的类,能根据ModuleModel中的定义自动生成一个model。先在module目录下面建立一个新的目录factory ,然后在这个下面建立一个文件 ModelFactory.js,内容如下:

/**
* 根据module的数据来生成模块的model
*/
Ext.define('app.view.module.factory.ModelFactory', {
// 静态变量或函数
statics: {
// 生成module的model,传入的数据是ModelModel中的data
getModelByModule: function (moduleModel) {
console.log('moduleModel');
console.log(moduleModel);
var module = moduleModel.data;
return Ext.define('app.model.' + module.tf_moduleName, {
extend: 'Ext.data.Model',
module: module,
idProperty: module.tf_primaryKey, // 设置模块model的主键
nameFields: module.tf_nameFields, // 设置模块model的名称字段
fields: this.getFields(module), // 设置字段 // 取得主键值
getIdValue: function () {
return this.get(this.idProperty);
}, // 取得当前记录的名字字段
getNameValue: function () {
if (this.nameFields)
return this.get(this.nameFields);
else
return null;
}
});
}, // 根据字段字义数组来生成model中的各个字段
getFields: function (module) {
var fields = []; for (var i in module.tf_fields) {
var fd = module.tf_fields[i];
var field = {
name: fd.tf_fieldName,
title: fd.tf_title,
type: this.getTypeByStr(fd.tf_fieldType)
};
if (field.type == 'string') {
field.useNull = true;
field.serialize = this.convertToNull;
}
if (field.type == 'date') {
field.dateWriteFormat = 'Y-m-d'; // 设置日期字段的读写格式
field.dateReadFormat = 'Y-m-d';
}
if (field.type == 'datetime')
field.dateReadFormat = 'Y-m-d H:i:s';
fields.push(field);
}
return fields;
},
// 将java中的数据类型转换成extjs5的字段类型
getTypeByStr: function (str) {
switch (str) {
case 'String':
return 'string';
case 'Boolean':
return 'boolean';
case 'Integer':
return 'int';
case 'Date':
return 'date';
case 'Datetime':
return 'date';
case 'Double':
case 'Float':
case 'Percent':
return 'float';
default:
return 'string';
}
}, // 如果是空字符串,返回null
convertToNull: function (v) {
return v ? v : null;
}
}
});

上面是生成model的一个类。下面再继续看最上面的ModuleModel.js中data下的另一个属性:tf_gridSchemes,这个属性下的数据是用来定义grid的分组和列,tf_schemeGroups 是定义了若干个分组,tf_groupFields定义这些分组下面的具体的列。这些数据以后也都是保存在数据库中的,只要建立三张表,一张放方案名称,一张放分组名牌,一张放分组下面的字段定义。对表进行修改,就能把数据传给前台,重新展示就是新的一个grid的列方案。并且方案可以制订多个,在界面中方全的切换。

下面的任务就是要为grid 生成columns,与上面生成model的方法相同,建立一个ColumnFactory.js程序,用来根据配置文件生成columns。

/**
* 用于生成Grid的Columns的类
*/ Ext.define('app.view.module.factory.ColumnsFactory', { statics: {
getColumns: function (moduleModel, schemeOrderId) { var scheme = moduleModel.get('tf_gridSchemes')[0]; // 取得第一个grid的方案
var columns = [];
for (var i in scheme.tf_schemeGroups) {
var sg = scheme.tf_schemeGroups[i];
// 是否需要显示分组
var isgroup = sg.tf_isShowHeaderSpans;
var group = {
gridGroupId: sg.tf_gridGroupId,
text: sg.tf_gridGroupName,
locked: sg.tf_isLocked,
//flex : 1,
columns: []
}
for (var j in sg.tf_groupFields) {
var gf = sg.tf_groupFields[j];
var fd = moduleModel.getFieldDefine(gf.tf_fieldId);
var field;
if (fd.tf_isHidden)
continue;
field = this.getColumn(gf, fd, moduleModel);
field.locked = sg.tf_isLocked;
if (isgroup) {
this.canReduceTitle(group, field);
group.columns.push(field);
} else
columns.push(field);
}
if (isgroup) {
this.canReduceTitle(group, field);
columns.push(group);
}
}
console.log(columns);
return columns;
}, // 看看分组名称是不是 下面column 的开头,如果是开头的话,并且columntitle 后面有内容,就把
// 相同的部分截掉
canReduceTitle: function (group, field) {
if (field.text.indexOf(group.text) == 0) {
field.text = field.text.slice(group.text.length).replace('(', '')
.replace(')', '').replace('(', '').replace(')', '');
if (field.text.indexOf("<br/>") == 0)
field.text = field.text.slice(5);
}
}, /**
* 根据groupField,fieldDefine的定义,生成一个column的定义
*/
getColumn: function (gf, fd, module) { // console.log(fd);
var ft = fd.tf_title.replace(new RegExp('--', 'gm'), '<br/>');
if (fd.behindText)
ft += '<br/>(' + fd.behindText + ')'; var field = {
filter: {},
maxWidth: 800,
gridFieldId: gf.tf_gridFieldId, // 加上这个属性,用于在列改变了宽度过后,传到后台
sortable: true,
text: ft,
dataIndex: fd.tf_fieldName
} switch (fd.tf_fieldType) {
case 'Date':
Ext.apply(field, {
xtype: 'datecolumn',
align: 'center',
width: 100
});
break; case 'Datetime':
Ext.apply(field, {
xtype: 'datecolumn',
align: 'center',
width: 130
});
break; case 'Boolean':
field.xtype = 'checkcolumn';
field.stopSelection = false;
field.processEvent = function (type) {
if (type == 'click')
return false;
};
break;
case 'Integer':
Ext.apply(field, {
align: 'center',
xtype: 'numbercolumn',
tdCls: 'intcolor',
format: '#'
});
break;
case 'Double':
Ext.apply(field, {
align: 'center',
xtype: 'numbercolumn',
width: 110
});
break;
case 'Float':
Ext.apply(field, {
align: 'center',
xtype: 'numbercolumn',
width: 110
});
break;
case 'Percent':
Ext.apply(field, {
align: 'center',
xtype: 'numbercolumn',
width: 110
})
break;
case 'String': break;
default:
break;
}
if (fd.tf_allowSummary) {
Ext.apply(field, {
hasSummary: true,
summaryType: 'sum'
})
} if (gf.tf_columnWidth > 0)
field.width = gf.tf_columnWidth;
else if (gf.tf_columnWidth == -1) {
field.flex = 1;
field.minWidth = 120;
}
return field;
}, /**
* 对于当前模块的name字段,加粗显示
*/ nameFieldRenderer: function (val, rd, model, row, col, store, gridview) {
return filterTextSetBk(store, '<strong>' + val + '</strong>');
}
}
});

文件的结构:

13、手把手教你Extjs5(十三)模块字段和Grid列的定义[1]的更多相关文章

  1. 14、手把手教你Extjs5(十四)模块字段和Grid列的定义[2]

    model和columns生成好了,下面要修改一下Module.js和Grid.js中的代码,使其能够协同工作. /** * 一个模块的主控界面的容器,用来安放各个模块控件以及协调他们之间的关系 */ ...

  2. 16、手把手教你Extjs5(十六)Grid金额字段单位MVVM方式的选择

    这一节来完成Grid中的金额字段的金额单位的转换.转换旰使用MVVM特性,总体上和控制菜单的几种模式类似.首先在目录app/view/main/menu下建立文件Monetary.js,用于放金额单位 ...

  3. 22、手把手教你Extjs5(二十二)模块Form的自定义的设计[1]

    下面开始设计和完成一个简单的Form的自定义过程.先准备数据,在ModuleModel.js中的data属性下面,加入自定义Form的参数定义,下面的代码中定义了一个新的属性tf_formScheme ...

  4. 20、手把手教你Extjs5(二十)模块Grid的多列表方案

    对于有很多字段的模块在一个grid中显示所有的字段,会显得很臃肿,对于不同的用户其侧重的字段类型也不尽相同,因此就有必要为Grid的列表设计多个方案.在这个自定义系统进行设计的时候,我已经将这部分内容 ...

  5. 19、手把手教你Extjs5(十九)模块Grid的其他功能的设想

    经过对自定义模块和Grid的设计和编码,现在已经能对一个有配置信息的模块来生成界面并进行一些简单的CURD操作.由于这是一个全解释性的前台的架构,因此你想到的任何新主意都可以放到所有的模块中. 比如对 ...

  6. 手把手教Linux驱动2-之模块参数和符号导出

    通过<手把手教Linux驱动1-模块化编程,玩转module>的学习,我们已经掌握了如何向内核加载一个模块,现在我们学习模块之间如何传递参数. 一.给模块传递参数 当我们加载一个模块到Li ...

  7. 23、手把手教你Extjs5(二十三)模块Form的自定义的设计[2]

    在本节中将要加入各种类型的字段,在加入字段的时候由于可以一行加入多个字段,因此层次结构又多了一层fieldcontainer.form里面的主要层次结构如下: form -- fieldSet -- ...

  8. 18、手把手教你Extjs5(十八)模块记录的拖放删除、拖放复制新增

    网页当中的拖放(drag-drop)是比较有趣的操作,extjs5中很好的封装了拖放的动作,也有各种类来支持,但是要学好“拖放”这个东西真是很难,特别是象我这样英语不好的人,看不太懂官网上的说明,做一 ...

  9. 21、手把手教你Extjs5(二十一)模块Form的自定义的设计

    前面几节完成了模块Grid的自定义,模块Form自定义的过程和Grid的过程类似,但是要更复杂一些.先来设计一下要完成的总体目标. 1、可以有多个Form方案,对应于显示.新增.修改.审核.审批等功能 ...

随机推荐

  1. scrollview上面的图片不上下滑动

    self.automaticallyAdjustsScrollViewInsets= NO;

  2. KVO 进阶

    Key-value coding (KVC) 和 key-value observing (KVO) 是两种能让我们驾驭 Objective-C 动态特性并简化代码的机制.在这篇文章里,我们将接触一些 ...

  3. Bitmap与Matrix旋转ImageView

    Bitmap与Matrix旋转ImageView 标签: matrixfloatbutton测试importlayout 2010-08-23 22:18 8569人阅读 评论(0) 收藏 举报  分 ...

  4. java数据结构之有序表查找

    这篇文章是关于有序表的查找,主要包括了顺序查找的优化用法.折半查找.插值查找.斐波那契查找: 顺序优化查找:效率极为底下,但是算法简单,适用于小型数据查找: 折半查找:又称为二分查找,它是从查找表的中 ...

  5. 完整版getByClass2016/4/20

    function getByclass(parent,sclass) { var re=new RegExp('\\b'+sclass+'\\b','i') var aEli=parent.getEl ...

  6. android ApplicationContext Context Activity 内存的一些学习

    Android中context可以作很多操作,但是最主要的功能是加载和访问资源. 在android中有两种context,一种是application context,一种是activity cont ...

  7. tomcat配置文件server.xml参数说明

    元素名 属性 解释 server port 指定一个端口,这个端口负责监听关闭tomcat 的请求 shutdown 指定向端口发送的命令字符串 service name 指定service 的名字 ...

  8. psy & obv

    PSY和OBV 1,PSY心理线是投资者对股市涨跌产生心理波动的情绪指标.相反,当PSY曲线向下跌破PSYMA曲线后,为卖出时机..当PSY曲线向上突破PSYMA曲线后,开始向下回调至PSYMA曲线, ...

  9. iptables配置vsftp访问

    一.FTP服务简介    FTP服务器有两种工作模式:主动模式和被动模式.这两种方式的特点如下:  (1)主动模式下:  tcp, 20(20号端口用于数据传输),21(21号端口用于控制连接) (2 ...

  10. 基于ATmgea8单片机设计的加热控制系统(转)

    源:http://blog.163.com/zhaojun_xf/blog/static/3005058020085102562729/ 1 引言 温度是工业生产中主要的被控参数之一,与之相关的各种温 ...