当前位置: 代码迷 >> Web前端 >> Ext2.0代码追踪:GridPanel只有一行记录时,字段修改也触发select事件
  详细解决方案

Ext2.0代码追踪:GridPanel只有一行记录时,字段修改也触发select事件

热度:522   发布时间:2012-10-25 10:58:57.0
Ext2.0代码跟踪:GridPanel只有一行记录时,字段修改也触发select事件

背景:

界面有两个GridPanel,分别为发票列表、费用列表。一个必要对应多个费用进行核销。

应用上,选择一个发票记录时,自动加载对应的同一业务下的费用,并计算出总费用金额。将费用总金额回写到选择的发票核销金额字段。

当发票有多行记录时,一切正常。当发票只有一条时,发生死循环。

?

调试:初步调试发现,如果只有一条发票时,费用加载完自己又清除掉,然后再加载。

?? ? ? ?查看Ext源代码,发现为Ext2.0的一个bug。在Ext2.2以后都已经解决。

?

过程:

1,回写发票的核销金额时,调用了Record的set方法。

?

set : function(name, value){
        if(String(this.data[name]) == String(value)){
            return;
        }
        this.dirty = true;
        if(!this.modified){
            this.modified = {};
        }
        if(typeof this.modified[name] == 'undefined'){
            this.modified[name] = this.data[name];
        }
        this.data[name] = value;
        if(!this.editing && this.store){
            this.store.afterEdit(this);
        }
    }

?

? 2,Store的afterEdit方法,触发update事件

?

 // private
    afterEdit : function(record){
        if(this.modified.indexOf(record) == -1){
            this.modified.push(record);
        }
        this.fireEvent("update", this, record, Ext.data.Record.EDIT);//触发事件,查看相关的监听者,猜测在GridView或GridPanel
    },

?

? 3,GridView监听了store的update事件,进而触发了onUpdate方法。

而onUpdate直接调用了refreshRow方法。

这里,可以看到当Record改变时,GridView采取的方法是先insertRowsonRemove。最后才触发rowupdated事件。跟踪过rowupdated事件的监听者,未发现异常。

因为是只有一行记录才出现问题,所以需要对数字的判断敏感一些。

当只有一条Record时,在insertRows方法中,实际只是刷新了一下。并没有真正的删除。

接下去就是看refresh方法做什么?

?

// private
    initData : function(ds, cm){
        if(this.ds){
            //省略……
        }
        if(ds){
            ds.on("load", this.onLoad, this);
            ds.on("datachanged", this.onDataChange, this);
            ds.on("add", this.onAdd, this);
            ds.on("remove", this.onRemove, this);
            ds.on("update", this.onUpdate, this);
            ds.on("clear", this.onClear, this);
        }
        this.ds = ds;
       //省略....
    },
// private
    onUpdate : function(ds, record){
        this.refreshRow(record);
    },
// private
    refreshRow : function(record){
        var ds = this.ds, index;
        if(typeof record == 'number'){
            index = record;
            record = ds.getAt(index);
        }else{
            index = ds.indexOf(record);
        }
        var cls = [];
        this.insertRows(ds, index, index, true);
        this.getRow(index).rowIndex = index;
        this.onRemove(ds, record, index+1, true);
        this.fireEvent("rowupdated", this, index, record);
    },
insertRows : function(dm, firstRow, lastRow, isUpdate){
        if(firstRow === 0 && lastRow == dm.getCount()-1){
            this.refresh();
        }else{
            if(!isUpdate){
                this.fireEvent("beforerowsinserted", this, firstRow, lastRow);
            }
            var html = this.renderRows(firstRow, lastRow);
            var before = this.getRow(firstRow);
            if(before){
                Ext.DomHelper.insertHtml('beforeBegin', before, html);
            }else{
                Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
            }
            if(!isUpdate){
                this.fireEvent("rowsinserted", this, firstRow, lastRow);
                this.processRows(firstRow);
            }
        }
    }
?

?

4,GridView的refresh触发了refresh事件,进而触发Ext.grid.RowSelectionModel的onRefresh函数。

直接便抛出了选择修改事件。

?

 onRefresh : function(){
        var ds = this.grid.store, index;
        var s = this.getSelections();
        this.clearSelections(true);
        for(var i = 0, len = s.length; i < len; i++){
            var r = s[i];
            if((index = ds.indexOfId(r.id)) != -1){
                this.selectRow(index, true);
            }
        }
        if(s.length != this.selections.getCount()){
            this.fireEvent("selectionchange", this);
        }
    }
?

?

?

综合上代码跟踪。第3步中的GridView的insertRows方法调用了refresh()是导致问题所在。则重写此方法解决此问题。

?

/**
 * 解决Grid只有一条数据时,对该记录调用set方法时,会造成刷新/选择事件
 *20101125.1 By  Simon
 */
Ext.grid.GridView.prototype.insertRows = function(dm, firstRow, lastRow, isUpdate) {
	if (!isUpdate && firstRow === 0 && lastRow >= dm.getCount() - 1) {//加入判断是否只是update
		this.refresh();
	} else {
		if (!isUpdate) {
			this.fireEvent("beforerowsinserted", this, firstRow, lastRow);
		}
		var html = this.renderRows(firstRow, lastRow);
		var before = this.getRow(firstRow);
		if (before) {
			Ext.DomHelper.insertHtml('beforeBegin', before, html);
		} else {
			Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
		}
		if (!isUpdate) {
			this.fireEvent("rowsinserted", this, firstRow, lastRow);
			this.processRows(firstRow);
		}
	}
	this.syncFocusEl(firstRow);
};
?

?

?

?

?

?

  相关解决方案