ExtJS Grid 分组中groupTextTpl的参数使用

在我们使用ExtJS的表格组件(Grid)中经常会需要使用到分组的情况,像使用业务分组,然后组内显示该业务下挂的服务列表信息。通常情况下,分组数据的方式就有两种:服务端分组数据返回或者是客户端分组。在ExtJS的API文档中给出的示例也非常简单,其代码如下:

var grid = new Ext.grid.GridPanel({
    // A groupingStore is required for a GroupingView
    store: new Ext.data.GroupingStore({
        reader: reader,
        data: xg.dummyData,
        sortInfo:{field: 'company', direction: "ASC"},
        groupField:'industry'
    }),

    columns: [
        {id:'company',header: "Company", width: 60, sortable: true, dataIndex: 'company'},
        {header: "Price", width: 20, sortable: true, renderer: Ext.util.Format.usMoney, dataIndex: 'price'},
        {header: "Change", width: 20, sortable: true, dataIndex: 'change', renderer: Ext.util.Format.usMoney},
        {header: "Industry", width: 20, sortable: true, dataIndex: 'industry'},
        {header: "Last Updated", width: 20, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}
    ],

    view: new Ext.grid.GroupingView({
        forceFit:true,
        // custom grouping text template to display the number of items per group
        groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
    }),

    frame:true,
    width: 700,
    height: 450,
    collapsible: true,
    animCollapse: false,
    title: 'Grouping Example',
    iconCls: 'icon-grid',
    renderTo: document.body
});

这里需要指出的时,在大多数文档和示例代码中归于分组列头的显示都是使用本示例中的代码:

groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'

很少有代码提及关于groupTextTpl的其它相关内容。

在API文档中提及groupTextTpl的介绍中提到了以下几个可以使用的属性调用:

  • group 显示分组列名的名称,如果使用emptypGroupText属性,那么当原始Group的值为空时,将会显示emptyGroupText的值。
  • gvalue 显示分组列的原始值,如果原始值为空,显示也是空。不会调用emptyGroupText。
  • text 如果配置了header属性,则会使用header属性的值加上原始分组列内的值。如果原始值为空,会调用emptyGroupText的值。
  • groupId ExtJS对每一个分组分配的独立的编号,通常其组成如下:ext-{生成器编码如gen20,gen19等}-gp-{分组列名}-{分组列值}
  • startRow 每一个组在整个Grid当前分页中的起始行的索引,索引从0开始。
  • rs 每个组包含的结果集。
  • cls 分组头样式的class名称
  • style : 分组头样式

比如在一些场景下,有业务和服务之分,服务是从属于业务的,业务和服务均会提供相应的编号和名称,这种情况下会按照业务编号分组,而希望显示的分组头内容为业务名称,而组内排序需要使用服务编号来排序。在这种情况下,我们可以这么定义:

比如业务名称和编号的列定义为appId,appName,服务名称和编号的列定义为serviceId,serviceName。

var myDataStore = new Ext.data.GroupStroe({
    autoLoad: false,
    url:'loadata.do',
    sortInfo:{field:'serviceId',direction:'DESC'}, // 这个属性必须配置,顺序可以为DESC或者ASC
    reader: reader,
    groupField:'appId'
});

//定义Grid,不显示业务名称、业务编号和服务编号
var mygrid = new Ext.grid.GridPanel  ({
    store: mydatastore,
    columns: [
        {header: '业务名称', width:45, dataindex: 'appName',hidden:true,groupable:false,dataIndex:"appName"},
        {header: '业务编号', width:55, dataindex: 'appId',hidden:true,groupable:false,dataIndex:"appId"},
        {header: '服务编号', width:70, dataindex: 'serviceId',hidden:true,groupable:false,dataIndex:"serviceId"},
        {header: '服务名称',  width:90, dataindex: 'serviceName'},
        {header: '其它内容',  width:40, dataindex: 'otherInfo'}
    ],
    stripeRows: true,
    autoSizeColumns: true,
    autoSizeGrid: true,
    title:'Your Grid Title',
    collapsible: false,
    animCollapse: false,
    height: 445,
    columnLines: true
});

下面如果我们需要在分组头显示业务名称的时候,我们就需要在GridPanel对象中定义view对象:

view: new Ext.grid.GroupingView({
    forceFit:true,
    groupTextTpl: '分组 : {text}|{[ values.rs[0].data["appName"] ]} ({[values.rs.length]} {[values.rs.length > 1 ? "Sevices" :        "Sevice"]})'
})

使用这个视图定义后,显示的分组头部文字效果就类似如下:

//比如数据形如:
//[
// {appId:'1',appName:'业务1',serviceId:'1001',serviceName:'服务1'},
// {appId:'1',appName:'业务1',serviceId:'1002',serviceName:'服务2'},
// {appId:'2',appName:'业务2',serviceId:'2001',serviceName:'服务3'},
// {appId:'2',appName:'业务2',serviceId:'2002',serviceName:'服务4'},
// {appId:'3',appName:'业务3',serviceId:'3001',serviceName:'服务5'}
//]
// 显示在表格中的头部效果如下:
// 分组: 1 | 业务1 (2 Services)
// 分组: 2 | 业务2 (2 Services)
// 分组: 3 | 业务3 (1 Service)

撰写本文的目的是因为在实际的产品开发中遇到类似的需求,为了不修改了后台的排序代码,于是进行了以上的尝试。这说明在使用ExtJS时,其API文档可能有些内容并没有提到,但是要能从其文档中慢慢发现API的规律,并予以尝试,肯定会带来不少帮助的。

官方示例中只给出了values.rs.length的示例,那么从这里面我们就能发现values.rs肯定是这个组内的所有结果集了,这样要实现我们本身的需求目的就非常简单了。