读书人

ExtJs兑现刷新Grid单个单元格

发布时间: 2012-09-21 15:47:26 作者: rapoo

ExtJs实现刷新Grid单个单元格

产生问题背景:

ExtJS3.2版本

页面上存在定时刷新表格的功能,而且表格中每行又有详情,当每次刷新每行时,即执行了Record的Set方法,详情都会关闭。刚开始觉得很奇怪。因为我一直觉得,我刷新一行中的一个字段的话,那应该是只更新这个字段的DOM就行了。

?

后台查看了一下源代码原来,每个Record数据变化时,其实都是重新生成一条新行的DOM。在源代码的执行步骤是,先新插入一行,再把旧数据的行DOM删除换。

?

由于详情是属于行的,所以,每次执行Record的Set后,行重新生成,那么详情肯定会删除掉。

?

为了解决详情不关闭这个问题,我们想方法为Record自定义一个Replace方法出来。

?

它的功能是:使用Record的Replace方法,可以实现单个字段的更新。

?

看起来很空间的一句话,可是为了实现这个功能,重写了ExtJs很多的“类”才实现了。下面是为了实现这个功能代码,

?

还带了实现了一个功能,使用ExtJs提供的冒泡提示加到表格的字段值中。

Ext.onReady(function(){//要使用ExtJS提供的冒泡提示,必须加上下面这句Ext.QuickTips.init();Ext.override(Ext.grid.ColumnModel,{//根据列定义时的给出的ID,得到该列的渲染方法,其实是为了更新单个单元格时,显示与定义一致getRendererById:function(id){return this.getRenderer(this.getIndexById(id));}});//步骤4:Ext.data.Record.REPLACE = 'repalce';//定义一个记录的替换命令,目前没有什么作用Ext.override(Ext.data.Record,{//替换单个字段的值的方法replace : function(name, value){var encode = Ext.isPrimitive(value) ? String : Ext.encode;if(encode(this.data[name]) == encode(value)) {return;}        this.dirty = true;if(!this.modified){this.modified = {};}if(this.modified[name] === undefined){this.modified[name] = this.data[name];}this.data[name] = value;//模型更新this.afterReplace(name,value);//通过Store通知gridview视图更新},//通过Store通知gridview视图更新方法afterReplace:function(name,value){ if (this.store != undefined && typeof this.store.afterReplace == "function") {this.store.afterReplace(this,name,value);}}    });//步骤5:Ext.override(Ext.data.Store,{//新定义的通知gridview视图更新的方法    afterReplace : function(record,name,value){if(this.modified.indexOf(record) == -1){this.modified.push(record);}//通知视图更新this.fireEvent('repalce',record,name,value, Ext.data.Record.REPLACE);}});    var myData = [        ['3m Co',71.72,0.02,0.03,'9/1 12:00am'],        ['Alcoa Inc',29.01,0.42,1.47,'9/1 12:00am'],        ['Altria Group Inc',83.81,0.28,0.34,'9/1 12:00am']    ];    // example of custom renderer function    function change(val){        if(val > 0){            return '<span qtip="'+val+'" style="color:green;">' + val + '</span>';        }else if(val < 0){            return '<span qtip="'+val+'" style="color:red;">' + val + '</span>';        }        return val;    }//使用ExtJS提供的冒泡提示function titleQtip(val){return '<span qtip="'+val+'">' + val + '</span>';}    // example of custom renderer function    function pctChange(val){        if(val > 0){            return '<span style="color:green;">' + val + '%</span>';        }else if(val < 0){            return '<span style="color:red;">' + val + '%</span>';        }        return val;    }    // create the data store    var store = new Ext.data.Store({        proxy: new Ext.ux.data.PagingMemoryProxy(myData),        remoteSort:true,        sortInfo: {field:'price', direction:'ASC'},        reader: new Ext.data.ArrayReader({            fields: [               {name: 'company'},               {name: 'price', type: 'float'},               {name: 'change', type: 'float'},               {name: 'pctChange', type: 'float'},               {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}            ]        })    });Ext.override(Ext.grid.GridView,{////步骤7:真正实现GridView更新单个单元格的方法onReplace:function(record,name,value){ var ds = this.ds, index;if(Ext.isNumber(record)){index = record;record = ds.getAt(index);if(!record){return;}}else{index = ds.indexOf(record);if(index < 0){return;}}//实现单个字段的更新document.getElementById(index+name).innerHTML = this.cm.getRendererById(name).call(this,value);},//步骤6:initData : function(ds, cm){        if(this.ds){            this.ds.un('load', this.onLoad, this);            this.ds.un('datachanged', this.onDataChange, this);            this.ds.un('add', this.onAdd, this);            this.ds.un('remove', this.onRemove, this);            this.ds.un('update', this.onUpdate, this);            this.ds.un('clear', this.onClear, this);//表格销毁时把这个监听放弃this.ds.un('repalce', this.onReplace, this);            if(this.ds !== ds && this.ds.autoDestroy){                this.ds.destroy();            }        }        if(ds){            ds.on({                scope: this,                load: this.onLoad,                datachanged: this.onDataChange,                add: this.onAdd,                remove: this.onRemove,                update: this.onUpdate,                clear: this.onClear,//当表格加载Store时,把这个监听添加上repalce: this.onReplace            });        }        this.ds = ds;        if(this.cm){            this.cm.un('configchange', this.onColConfigChange, this);            this.cm.un('widthchange', this.onColWidthChange, this);            this.cm.un('headerchange', this.onHeaderChange, this);            this.cm.un('hiddenchange', this.onHiddenChange, this);            this.cm.un('columnmoved', this.onColumnMove, this);        }        if(cm){            delete this.lastViewWidth;            cm.on({                scope: this,                configchange: this.onColConfigChange,                widthchange: this.onColWidthChange,                headerchange: this.onHeaderChange,                hiddenchange: this.onHiddenChange,                columnmoved: this.onColumnMove            });        }        this.cm = cm;    },doRender : function(columns, records, store, startRow, colCount, stripe) {        var templates    = this.templates,            cellTemplate = templates.cell,            rowTemplate  = templates.row,            last         = colCount - 1;        var tstyle = 'width:' + this.getTotalWidth() + ';';        // buffers        var rowBuffer = [],            colBuffer = [],            rowParams = {tstyle: tstyle},            meta      = {},            column,            record;        //build up each row's HTML        for (var j = 0, len = records.length; j < len; j++) {            record    = records[j];            colBuffer = [];            var rowIndex = j + startRow;            //build up each column's HTML            for (var i = 0; i < colCount; i++) {                column = columns[i];                meta.id    = column.id;                meta.css   = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');                meta.attr  = meta.cellAttr = '';                meta.style = column.style;                meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);//步骤2:定义这个字段的DIV的ID,这个地方是关键,否则我们通过document.getElementById找不到这个DIV,也就不可以实现这个功能了。meta.divId = j+column.name;                if (Ext.isEmpty(meta.value)) {                    meta.value = ' ';                }                if (this.markDirty && record.dirty && Ext.isDefined(record.modified[column.name])) {                    meta.css += ' x-grid3-dirty-cell';                }                colBuffer[colBuffer.length] = cellTemplate.apply(meta);            }            //set up row striping and row dirtiness CSS classes            var alt = [];            if (stripe && ((rowIndex + 1) % 2 === 0)) {                alt[0] = 'x-grid3-row-alt';            }            if (record.dirty) {                alt[1] = ' x-grid3-dirty-row';            }            rowParams.cols = colCount;            if (this.getRowClass) {                alt[2] = this.getRowClass(record, rowIndex, rowParams, store);            }            rowParams.alt   = alt.join(' ');            rowParams.cells = colBuffer.join('');            rowBuffer[rowBuffer.length] = rowTemplate.apply(rowParams);        }        return rowBuffer.join('');    }});var ts = {};ts.cell = new Ext.Template('<td style="{style}" tabIndex="0" {cellAttr}>',//步骤1:本来是打开在GridView重写这部分,可是发现代码太多,觉得没有必要,在这里直接定义为Div添加一个id的属性即可。'<div  id=\'{divId}\' unselectable="on" {attr}>{value}</div>','</td>');    // create the Grid    var grid = new Ext.grid.GridPanel({        store: store,//步骤3:注意在添加这个属性viewConfig:{templates:ts},        columns: [            {id:'company',header: "Company", width: 160, sortable: true,renderer: titleQtip, dataIndex: 'company'},            {header: "Price", width: 75, sortable: true, renderer: 'usMoney', dataIndex: 'price'},            {id:'change',header: "Change", width: 75, sortable: true, renderer: change, dataIndex: 'change'},            {header: "% Change", width: 75, sortable: true, renderer: pctChange, dataIndex: 'pctChange'},            {header: "Last Updated", width: 85, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}        ],        stripeRows: true,        autoExpandColumn: 'company',        height:320,        width:600,        frame:true,        title:'Sliding Pager',id:'maingrid',        plugins: new Ext.ux.PanelResizer({            minHeight: 100        }),        bbar: new Ext.PagingToolbar({            pageSize: 10,            store: store,            displayInfo: true        })    });    grid.render('grid-example');    store.load({params:{start:0, limit:10}});//alert(document.getElementById('1pctChange').innerHTML);});//测试该功能的代码function change(){//修改第2行的company这个字段的值Ext.getCmp('maingrid').store.getAt(1).replace('company','ddddd');}

?

?

?

?

?

?

?

1 楼 bing_zz 2011-10-28 不怎么详细,猜来猜去还是不知道要实现的是什么,可不可以把你实现后截个图。
看来我的道行不够,也不知道此文是否能够解决我的问题,只有一个核心代码,还原实现时间太紧带风险。
lyndon.lin辛苦了。 2 楼 lyndon.lin 2011-11-03 ExtJs自带表格更新更新功能,更新一行,我写的这个是只更新一行中的某个字段。

读书人网 >JavaScript

热点推荐