`

实现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格式使用的多。

分享到:
评论

相关推荐

    DynamicGrid:示例-具有动态模型的动态网格-Extjs插件

    xtype: 'dynamicGrid', url: '/some/url' } ] }); 还要检查另一个分支: 定义哪些列必须可见的可能性。 (Hadsch的补丁-谢谢)-可以在json响应中定义列和字段。 ExtJs 4.2 插件代码很短,很容易

    extjs动态表头,绝对的好东西啊

    这个"extjs动态表头"的资源很可能是一个插件或组件,名为`Ext.ux.grid.DynamicGridPanel.js`,它扩展了ExtJS的标准GridPanel,增加了动态调整列的能力。 动态表头的核心功能包括: 1. **实时编辑**:用户可以在...

    ExtJS4 2学习 21 动态菜单与表格数据展示操作总结篇

    在"ExtJS4 2学习 21 动态菜单与表格数据展示操作总结篇"中,我们将深入探讨两个核心组件:动态菜单(Dynamic Menus)和表格数据展示(Grid Data Display),以及如何在实际应用中进行操作。 动态菜单在Web应用中...

    ExtJs教程_完整版

    - **动态加载(Dynamic Loading)**:支持动态加载组件和数据,提高应用响应速度。 #### 四、国际化支持 - **多语言支持(Multi-Language Support)**:ExtJS提供了内置的语言包,使得开发者能够轻松地将应用本地化到...

    Extjs4.0 列隐藏和滚动条动态加载

    在ExtJS 4.0版本中,它提供了一系列功能,包括表格面板(Grid Panel)的列管理以及滚动条的动态加载。让我们深入探讨这些核心概念。 1. **列隐藏与显示** 在ExtJS 4.0中,表格面板允许用户动态隐藏或显示列,以...

    非常好的gwt-ext培训教程

    1. **表格(Grid)**: 支持排序、分页和过滤功能,便于数据管理和展示。 2. **树形视图(Tree)**: 具备拖拽功能,方便组织和操作层次结构的数据。 3. **组合下拉框(Combobox)**: 可高度定制,提供丰富的选项和...

    ExtAspNet_v2.3.2_dll

    -增加示例(data/grid_dynamic_columns.aspx)。 -修正Form不能自适应浏览器大小的改变(feedback:kaywood)(WorkItem#6309)。 -增加重载方法Alert.Show(message, title, icon)(feedback:TheBox)(WorkItem#6353)。 ...

    最好的gwt-ext学习资料

    Gwt-Ext正是在这两者基础上,实现了更高级别的封装,将ExtJs的JavaScript接口转化为Java接口,使得开发者能够在熟悉的Java环境中构建复杂的表现层,显著提升开发效率。 Gwt-Ext不仅提供了如表格(Grid)、分页、...

    ExtAspNet v2.2.1 (2009-4-1) 值得一看

    -增加示例(data/grid_dynamic_columns.aspx)。 -修正Form不能自适应浏览器大小的改变(feedback:kaywood)(WorkItem#6309)。 -增加重载方法Alert.Show(message, title, icon)(feedback:TheBox)(WorkItem#6353)。 ...

    GWT-Ext_体验之旅.doc

    GWT-Ext 的核心特点在于它扩展了 GWT,融合了 ExtJS 的丰富界面组件,包括有排序功能的表格(Grid)、分页、过滤、拖拽功能的树、自定义的组合下拉框(Combobox)、目录、对话框、表单(Form)等。 1. **GWT-Ext 的...

    UniGUI集合说明

    - 在“Kind of target file”下拉菜单中选择“Dynamic Library (.dll)”。 - 调整其他相关设置,如输出目录等。 - 最后保存设置并重新编译项目。 #### 5. UniGUI开发的dll如何发布 发布UniGUI开发的DLL涉及以下几...

    unigui0.83.5.820

    - UniTreeView: Node dynamic add/delete support - UniTreeView: Several Memory leak issues - UniDBGrid: DBGrid.Column.Visible bug - PageControl: Render problem in invisible tabs - TUniListBox: Items ...

Global site tag (gtag.js) - Google Analytics