跟我一起学extjs5(17--Grid金额字段单位MVVM方式的选择)
这一节来完毕Grid中的金额字段的金额单位的转换。转换旰使用MVVM特性,整体上和控制菜单的几种模式类似。首先在文件夹app/view/main/menu下建立文件Monetary.js。用于放金额单位的数据和生成菜单的items。
/** * 金额单位的管理类 */ Ext.define('app.view.main.menu.Monetary', { statics : { values : null, getAllMonetary : function() { if (!this.values) { // 初始化各种金额单位 元 千元 万元 百万元 亿元 this.values = new Ext.util.MixedCollection(); this.values.add('unit', this.createAMonetary('', 1, '元')); this.values.add('thousand', this.createAMonetary('千', 1000, '千元')); this.values.add('tenthousand', this.createAMonetary('万', 10000, '万元')); this.values.add('million', this.createAMonetary('M', 100 * 10000, '百万元')); this.values.add('hundredmillion', this.createAMonetary('亿', 10000 * 10000, '亿元')); } return this.values; }, // 生成菜单中的 items getMonetaryMenu : function() { var items = []; this.getAllMonetary().eachKey(function(key, item) { items.push({ text : item.unitText, value : key }) }) return items; }, createAMonetary : function(monetaryText, monetaryUnit, unitText) { return { monetaryText : monetaryText, // 跟在数值后面的金额单位文字,如 100.00万 monetaryUnit : monetaryUnit, // 显示的数值须要除的分子 unitText : unitText // 跟在字段后面的单位如 合同金额(万元) } }, getMonetary : function(key) { return this.getAllMonetary().get(key); } } })
{ text : '金额单位', menu : [{ xtype : 'segmentedbutton', reference : 'monetary', // 增加了这一句。在改变数据的时候能够触发bind绑定的事件 defaultUI : 'default', value : 'tenthousand', items : app.view.main.menu.Monetary.getMonetaryMenu() }] }
生成的菜单例如以下:
在MainModels.js中的data属性下增加
monetary : { // 金额单位 value : 'tenthousand' // 默认万元,以后能够从后台取得个人偏好设置,或者存放在cookies中 },
在MainController.js中增加金额变更事件绑定和运行函数。
init : function() { var vm = this.getView().getViewModel(); // 绑定金额单位改动过后须要去运行的程序 vm.bind('{monetary.value}', function(value) { this.onMonetaryChange(value); }, this) }, // 金额单位改动过后运行 onMonetaryChange : function(value) { console.log('金额单位变更:' + value); var m = app.view.main.menu.Monetary.getMonetary(value); Ext.monetaryText = m.monetaryText; // 设置当前的全局的金额单位 Ext.monetaryUnit = m.monetaryUnit; Ext.each(this.getView().query('modulegrid'), function(grid) { if (grid.rendered) { grid.getView().refresh(); Ext.Array.forEach(grid.columnManager.getColumns(), function(column) { // 假设能够改变大小。而且是金额字段,则在改变了金额单位以后,自己主动调整一下列宽 if (!column.resizeDisabled && column.fieldDefine && column.fieldDefine.tf_isCurrency) { column.autoSize(); } }) } }); }
经过以上几个步骤,在上节的基础上就能够更改金额单位。并实时的刷新全部已经打开的Grid中的金额字段,刷新了以后还会对金额字段又一次调整列宽。
上面展示了转换过金额单位后金额字段的值的展示。事件的流转步骤例如以下图:
对于Grid的column自己主动适应宽度,经过半天的研究。搞明确了一点,就是Renderer中,返回的应该是不加标签的值,详细的样式放在metaData中来定义。比方金额的Renderer函数改动为:(原来的函数看上一节)
// 金额字段 monetaryRenderer : function(val, metaData, model, row, col, store, gridview) { if (val) { if (Ext.monetaryUnit && Ext.monetaryUnit != 1) val = val / Ext.monetaryUnit; // 正数用蓝色显示。负数用红色显示,必须css和返回的值分开来设置,否则不能autoSize() metaData.style = 'color:' + (val > 0 ? 'blue' : 'red') + ';float:right;'; return Ext.util.Format.number(val, '0,000.00') + Ext.monetaryText; } else return ''; // 假设为0,则不显示 }原来把style的属性是放在返回的值里面的,这样在自己主动适应宽度的时候。extjs算不出究竟有多宽。这样分开设置后,自己主动适应宽度就正常了。然后是在column的定义里面也要改动一下,不能用formatter,而要用renderer。
比如对于整型的数据要改成这样:
case 'Integer' : Ext.apply(field, { align : 'center', xtype : 'numbercolumn', format : '#', renderer : Ext.util.Format.intRenderer, // formatter : 'intRenderer', editor : { xtype : 'numberfield' } }); break;