实现extjs的Dynamic Grid

我们知道,实现extjs的Grid必须先定义一个ColumnModel,指定列名称、列标题、宽度、对齐方式,然后定义一个Record和Store,指定数据源的字段名、类型,最后定义一个Grid,完整过程的代码类似如下:

     //  the column model has information about grid columns
     //  dataIndex maps the column to the specific data field in
     //  the data store (created below)
     var  cmCust  =   new  Ext.grid.ColumnModel([{
           header: 
" 客户编码 " ,
           dataIndex: 
' CUSTID ' ,
           width: 
70
        }, {
           header: 
" 客户简称 " ,
           dataIndex: 
' CUSTSHORTNAME ' ,
           width: 
200
        }, {    
           header: 
" 预收金额 " ,
           dataIndex: 
' PREPAYMENT ' ,
           width: 
100 ,
           align: 
' right ' ,
           renderer: Ext.util.Format.gbMoney
        },{
           header: 
" 应收金额 " ,
           dataIndex: 
' PAYMENT ' ,
           width: 
100 ,
           align: 
' right ' ,
           renderer: Ext.util.Format.gbMoney
        },{
           header: 
" 实际欠款 " ,
           dataIndex: 
' SJQK ' ,
           width: 
100 ,
           align: 
' right ' ,
           renderer: Ext.util.Format.gbMoney
        },{
           header: 
" 信用期限 " ,
           dataIndex: 
' LICENSEPERIOD ' ,
           width: 
100 ,
           align: 
' right '
        },{
           header: 
" 信用额度 " ,
           dataIndex: 
' LICENSEMONEY ' ,
           width: 
100 ,
           align: 
' right ' ,
           renderer: Ext.util.Format.gbMoney
        }]);

    
//  by default columns are sortable
    cmCust.defaultSortable  =   true ;

    
//  this could be inline, but we want to define the order record
     //  type so we can add records dynamically
     var  cust  =  Ext.data.Record.create([
           {name: 
' CUSTID ' , type:  ' string '  },
           {name: 
' CUSTSHORTNAME ' , type:  ' string ' },
           {name: 
' PREPAYMENT ' , type:  ' float ' },
           {name: 
' PAYMENT ' , type:  ' float ' },
           {name: 
' SJQK ' , type:  ' float ' },
           {name: 
' LICENSEPERIOD ' , type:  ' float ' },
           {name: 
' LICENSEMONEY ' , type:  ' float ' }
      ]);

    
//  create the Data Store
     var  dsCust  =   new  Ext.data.Store({
        
//  load using HTTP
        proxy:  new  Ext.data.HttpProxy({url:  ' ../getCustList.do ' }),
        
        
//  the return will be XML, so lets set up a reader
        reader:  new  Ext.data.DynamicXmlReader({
               
//  records will have a "customer" tag
               record:  ' table ' ,
               totalRecords: 
' records '
           }, cust)
    });

var  gridCust  =   new  Ext.grid.DynamicGrid(  ' customer-grid ' , {
        ds: dsCust,
        cm: cmCust,
        selModel: 
new  Ext.grid.RowSelectionModel(),
        enableColLock:
false ,
        loadMask: 
true ,    });

 gridCust.render();

此过程相当繁琐。很多情况下,我们需要一个通用的动态Grid,不必指定字段名、字段类型、列头等信息,而是根据返回记录(通常是json或xml格式)的结构和内容,自动将记录展现在Grid中,这就是Dynamic Grid。

extjs的论坛上有两种方式实现Dynamic Grid,一种是json,另一种是xml。前者请看http://extjs.com/learn/Ext_Extensions。对于xml方式,需要扩展Ext.data.XmlReader和Ext.grid.Grid,具体根据返回的xml的结构,假设返回的xml类似:

<? xml version="1.0" encoding="UTF-8" ?>
< response  success ='true'>
        
<database >
            
< record >
                
< SUPPLIERID > <![CDATA[ 1 ]]> </ SUPPLIERID >
                
< SUPPLIERSHORTNAME > <![CDATA[ 中原公司 ]]> </ SUPPLIERSHORTNAME >
                
< PREPAYMENT > <![CDATA[ 0.00000000 ]]> </ PREPAYMENT >
                
< PAYMENT > <![CDATA[ 0.00000000 ]]> </ PAYMENT >
                
< SJQK > <![CDATA[ 0.00000000 ]]> </ SJQK >
            
</ record >
            
< record >
                
< SUPPLIERID > <![CDATA[ 2 ]]> </ SUPPLIERID >
                
< SUPPLIERSHORTNAME > <![CDATA[ 广州市五金公司 ]]> </ SUPPLIERSHORTNAME >
                
< PREPAYMENT > <![CDATA[ 0.00000000 ]]> </ PREPAYMENT >
                
< PAYMENT > <![CDATA[ 6855.00000000 ]]> </ PAYMENT >
                
< SJQK > <![CDATA[ 6855.00000000 ]]> </ SJQK >
            
</ record >

                                            
</ database >
</ response >

在上面的xml内容中,每个<record>是一个记录,我们必须得到<record>中所有子元素的名称,做为Grid的列标题:

Ext.grid.DynamicColumnModel  =   function (store) {
    
var  cols  =  [];
    
var  recordType  =  store.reader.recordType;
    
var  fields  =  recordType.prototype.fields;
   
    
for  ( var  i  =   0 ; i  <  fields.keys.length; i ++ ) {
        
var  fieldName  =  fields.keys[i];
        
var  field  =  recordType.getField(fieldName);
        cols[i] 
=  {
            header: field.header,
            dataIndex: field.name,
            tooltip: field.tooltip,
            hidden: field.hidden,
            renderer: eval(field.renderer)
        };
    }
    Ext.grid.DynamicColumnModel.superclass.constructor.call(
this , cols);
};
Ext.extend(Ext.grid.DynamicColumnModel, Ext.grid.ColumnModel, {});

Ext.data.DynamicXmlReader 
=   function (config) {
    Ext.data.DynamicXmlReader.superclass.constructor.call(
this , config, []);
};
Ext.extend(Ext.data.DynamicXmlReader, Ext.data.XmlReader, {
    getRecordType : 
function (data) {
        recordDefinition = Ext.DomQuery.select( this.meta.record + ':first-child > *', data);
        
var  arr  =  [];
        
for  ( var  i  =   0 ; i  <  recordDefinition.length; i ++ ) {
            arr[i] 
=  {
                name:recordDefinition[i].tagName,
                header:recordDefinition[i].tagName
            };
        }

        
this .recordType  =  Ext.data.Record.create(arr);
        
return   this .recordType;
    },
       
    readRecords : 
function (doc) {
        
this .xmlData  =  doc;
        
var  root  =  doc.documentElement  ||  doc;
        
this .getRecordType(root);
        
return  Ext.data.DynamicXmlReader.superclass.readRecords.call( this , doc);
    }
});

Ext.grid.GridView.prototype.bindColumnModel 
=   function (cm) {
    
if ( this .cm){
        
this .cm.un( " widthchange " this .updateColumns,  this );
        
this .cm.un( " headerchange " this .updateHeaders,  this );
        
this .cm.un( " hiddenchange " this .handleHiddenChange,  this );
        
this .cm.un( " columnmoved " this .handleColumnMove,  this );
        
this .cm.un( " columnlockchange " this .handleLockChange,  this );
    }
    
if (cm){
        
this .generateRules(cm);
        cm.on(
" widthchange " this .updateColumns,  this );
        cm.on(
" headerchange " this .updateHeaders,  this );
        cm.on(
" hiddenchange " this .handleHiddenChange,  this );
        cm.on(
" columnmoved " this .handleColumnMove,  this );
        cm.on(
" columnlockchange " this .handleLockChange,  this );
    }
    
this .cm  =  cm;
};

Ext.grid.DynamicGrid 
=   function (container, config) {
    Ext.grid.DynamicGrid.superclass.constructor.call(
this , container, config);
};
Ext.extend(Ext.grid.DynamicGrid, Ext.grid.Grid, {
    render : 
function () {
        
this .dataSource.addListener( ' load ' this .doReconfiguration,  this );
        
this .colModel  =   new  Ext.grid.DefaultColumnModel([{ header:  '' , dataIndex:  ''  }]);
        Ext.grid.DynamicGrid.superclass.render.call(
this );
    },

    doReconfiguration : 
function () {
        
this .colModel  =   new  Ext.grid.DynamicColumnModel( this .dataSource);
        
this .view.bindColumnModel( this .colModel);
        
this .view.refresh( true );
        
// this.dataSource.removeListener("load", this.doReconfiguration);
    }
});

上面的代码实现了DynamicColumnModel、DynamicXmlReader和DynamicGrid,DynamicXmlReader根据xml文件的结构和内容,自动配置一个ColumnModel和Store,这样最终的Dynamic Grid实现代码如下所示:

var  dsCust  =   new  Ext.data.Store({
        
//  load using HTTP
        proxy:  new  Ext.data.HttpProxy({url:  ' ../getCustList.do ' }),    
        
//  the return will be XML, so lets set up a reader
        reader:  new  Ext.data.DynamicXmlReader({
               record: 
' record ' ,
               totalRecords: 
' records '
           })
    });

var  gridCust  =   new  Ext.grid.DynamicGrid(  ' customer-grid ' , {
        ds: dsCust,
        
// cm: cmCust,
        selModel:  new  Ext.grid.RowSelectionModel(),
        enableColLock:
false ,
        loadMask: 
true
    });
   gridCust.render();

相比本文开头的代码简化了很多。当然还有很多地方需要优化,例如实现描述性的列标题(而不是以字段名做为列标题),配置列宽和对齐方式,实现Dynamic EditorGrid等,通常我们还需要一个配置档,将这些原先硬编码的信息在配置档里配置好,然后在返回的json和xml中,除了有结果记录外,还有配置档中的meta信息,以便根据这些信息自动展现Dyanmic Grid。

相比而言,由于json较xml简洁,而且JsonReader本身就支持meta数据,使用JsonReader实现DynamicGrid较XmlReader方式简单,运行效率也高。当然,前提是必须将记录转换成json格式,目前json格式可能不如xml格式使用的多。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值