前文ExtJS4.2 Grid嵌套实例中讲解了如何在表格Grid中嵌套Grid,即外部Grid中每行分别展现为不同的内部Grid,比如常见的费用报销业务,费用类别有往返车费和住宿费,其中往返车费需要填写往返类型、交通工具、费用日期、出发地、目的地和金额,住宿费只需填写入住日期、离开日期、单价和金额,在一个表格中包含多种费用类别,每个费用类别下又有多条明细,所需实现的业务场景图片如:
在线演示 / 示例代码
由于前文未采用MVC模式来组织代码,代码可读性不强,本文将在前文基础上按照MVC模式来重新实现该业务场景,以供有需求的朋友参考学习。
外部表格Grid
外部表格Grid主要采用Ext.grid.plugin.RowExpander插件来实现在行记录里展示内部Grid,需设置ptype='rowexpander',并指定rowBodyTpl,同时pluginId设为'rowExpander'(后续需通过pluginId来获取插件对象),代码如下:
- Ext.define('Itdatum.view.UserList' ,{
- extend: 'Ext.grid.Panel',
- alias : 'widget.userlist',
- border : false,
- columnLines : true,
- columns : [ {
- align : 'left',
- dataIndex : 'feeitmtyp',
- exportable : true,
- header : '费用类别',
- id : 'fituitag12',
- menuDisabled : true,
- renderer : renderFeeItemType,
- style : 'text-align:center;',
- width : 200
- }, {
- align : 'left',
- dataIndex : 'rbmfndnam',
- exportable : true,
- hidden : true,
- id : 'fituitag13',
- menuDisabled : true,
- style : 'text-align:center;',
- width : 80
- }, {
- align : 'left',
- dataIndex : 'remark',
- exportable : true,
- flex : 1,
- header : '备注',
- id : 'fituitag14',
- menuDisabled : true,
- style : 'text-align:center;',
- width : 150
- }, {
- align : 'right',
- dataIndex : 'rbmtot',
- exportable : true,
- header : '金额',
- id : 'fituitag15',
- menuDisabled : true,
- style : 'text-align:center;',
- summaryType : 'sum',
- width : 100
- }, {
- align : 'left',
- dataIndex : 'rbmbeltyp',
- exportable : true,
- hidden : true,
- id : 'fituitag16',
- menuDisabled : true,
- style : 'text-align:center;',
- width : 80
- }, {
- align : 'center',
- exportable : false,
- header : '操作',
- id : 'actioncolumn17',
- items : [ {
- handler : deleteFeeItemType,
- iconCls : 'delete-default',
- id : 'button18',
- tooltip : '删除',
- xtype : 'button'
- } ],
- menuDisabled : true,
- style : 'text-align:center;',
- width : 80,
- xtype : 'actioncolumn'
- } ],
- fbar : [ {
- handler : doSubmit,
- iconCls : 'submit-default',
- id : 'bt_submit',
- text : '保存',
- xtype : 'button'
- }, {
- iconCls : 'reset-default',
- id : 'button11',
- text : '重置',
- xtype : 'button'
- } ],
- features : [ {
- ftype : 'summary',
- id : 'summary19'
- } ],
- forceFit : false,
- id : 'feeGrid',
- loadMask : true,
- plugins : [ {
- pluginId : 'rowExpander',
- ptype : 'rowexpander',
- rowBodyTpl : [
- '<div id="{feeitmtyp}">',
- '</div>'
- ]
- } ],
- selType : 'rowmodel',
- sortableColumns : false,
- store : 'FeeGridStore',
- stripeRows : true,
- tbar : [ {
- displayField : 'rbmfndnam',
- editable : false,
- fieldLabel : '添加费用类别',
- hiddenName : 'feeitmtyp',
- id : 'feeitmtyp',
- labelStyle : 'text-align:right',
- listeners : {
- 'select' : selectFeeItemType
- },
- name : 'feeitmtyp',
- repeatTriggerClick : true,
- store : createStore(),
- triggerAction : 'all',
- valueField : 'rbmfndcod',
- xtype : 'combo'
- } ],
- title : '费用报销明细',
- viewConfig : {
- enableTextSelection : true
- },
- initComponent: function() {
- this.callParent(arguments);
- }
- });
监听Grid.view的expandBody和collapsebody事件
同时监听Grid.store的add事件,即新增一种费用类别时,自动展开该费用类别的内部Grid。
- Ext.define('Itdatum.controller.UserController', {
- extend: 'Ext.app.Controller',
- views: [
- 'UserList','UserEdit'
- ],
- stores: [
- 'UserStore','FeeGridStore','WfcfGridStore','CcbtGridStore','SnjtfGridStore','ZsfGridStore'
- ],
- models: ['UserModel','FeeGridModel','WfcfInnerModel','CcbtInnerModel','SnjtfInnerModel','ZsfInnerModel'],
- init: function() {
- this.control({
- 'viewport > userlist': {
- itemdblclick: this.editUser
- },
- 'useredit button[action=save]': {
- click: this.updateUser
- },
- 'userlist': {
- afterrender: function(feeGrid){//侦听userlist渲染
- feeGrid.view.on('expandBody', function (rowNode, record, expandRow, eOpts) {
- var rbmbeltyp=record.get('rbmbeltyp');
- if(rbmbeltyp==='WFCF') {
- displayWfcfInnerGrid(record);
- }else if(rbmbeltyp==='SNJTF') {
- displaySnjtfInnerGrid(record);
- }else if(rbmbeltyp==='ZSF') {
- displayZsfInnerGrid(record);
- }else if(rbmbeltyp==='CCBT') {
- displayCcbtInnerGrid(record);
- }
- });
- feeGrid.view.on('collapsebody', function (rowNode, record, expandRow, eOpts) {
- var rbmbeltyp=record.get('rbmbeltyp');
- if(rbmbeltyp==='WFCF') {
- destroyWfcfInnerGrid(record);
- }else if(rbmbeltyp==='SNJTF') {
- destroySnjtfInnerGrid(record);
- }else if(rbmbeltyp==='ZSF') {
- destroyZsfInnerGrid(record);
- }else if(rbmbeltyp==='CCBT') {
- destroyCcbtInnerGrid(record);
- }
- });
- feeGrid.getStore().on('add',function( store, records, index, eOpts){
- //alert(records.length);
- feeGrid.getPlugin('rowExpander').toggleRow(index,records[0]);
- });
- }
- }
- });
- },
- editUser: function(grid, record) {
- alert('Edit User');
- //console.log('Double clicked on ' + record.get('name'));
- var view = Ext.widget('useredit');
- view.down('form').loadRecord(record);
- },
- updateUser: function(button) {
- alert('UpdateUser');
- //console.log('clicked the Save button');
- },
- onPanelRendered: function() {
- //console.log('The panel was rendered');
- }
- });
其他代码较多,不一一贴出来了,请自行研究在线实例。