Ext版本:4.2
需求描述:
系统中有大量的可编辑列表,用户可以动态的添加条目。每当添加条目的时候,新添加的条目的第一个可编辑单元格,自动获取焦点。如下图所示:
第一思路,就是监听GridPanel的add事件,一旦Grid添加条目就触发Focus事件。查看API发现,Grid根本就没有监听Store内容变化的事件。大多数是监听Grid包含组件的事件和view的事件。如下图:
所以,只能转变思路。监听Store的add事件,一旦Store添加条目,则触发Grid的Focus事件。但是,Grid和Store是多对一的关系,所以Grid类中持有Store的引用,但是Store中找不到Grid的引用。所以,不能简单的把对add事件的handler写在Store中。
那么,继续变换思路。既然Grid引用了Store,那么把对Store的监听事件写在Grid的类定义中。如下:
Ext.define("Soims.view.voyage.VoyageTask", {
extend: ‘Ext.grid.Panel‘,
alias: ‘widget.voyagetask‘,
plugins: [{ ptype: ‘cellediting‘, clicksToEdit: 1 }],
selType: ‘rowmodel‘,
initComponent: function () {
this.store = Ext.create(‘Soims.store.voyage.VoyageTask‘); // 关系引用
this.columns = [
// 略
}];
this.tbar = [{
text: ‘添加‘,
xtype: ‘button‘,
iconCls: ‘Add‘,
hidden: this.isShow,
itemId: ‘add‘
}];
this.store.on(‘add‘,this.onInsertRecord,this); // 注意:需要把this传递进去
this.callParent();
},
onInsertRecord: function (store, records, index,opt) {
var editor = this.getCellRowEditor(),
res;
console.log(editor);
console.log(this.getStore().getAt(0));
console.log(this.columns[0]);
res = editor.startEdit(this.getStore().getAt(0), this.columns[0]); // focus
console.log(res);
}
});这里有一点需要注意:就是给store的add绑定事件的时候,需要改变this指针。否则,在onIsertRecord()方法中,得不到Grid的引用。
事情还没有结束,因为结果出乎意料。虽然,监听事件执行了,但是Cell并没有Focus,查看输出结果,如下图:
也就是说,各个对象都能获取,但是不能正确出发startEdit()事件。
在startEdit()事件上加断点,很清楚的发现,当出发startEdit()的时候,Grid中还没有添加条目,如下图所示:
但是startEdit()事件,是需要当前触发行的context,如果找不到则不能编辑,如下图:
根据原因是,Store类的insert方法中,会触发add事件,从而处理各种监听事件,包括view的onAdd()添加Node,和我们自定义的onIsertRecord()触发焦点。由于先注册的事件后触发(跟浏览器有关吗?),导致我们的处理事件先被调用,导致了这个问题。
Store的insert方法源码:
insert: function(index, records) {
// 略..
me.fireEvent(‘add‘, me, out, index); // 触发方法
me.fireEvent(‘datachanged‘, me);
// 略..
}view的onAdd()调用顺序为:
BufferedRendererTableView.onAdd() -> Ext.view.Table.onAdd() -> Ext.view.AbstractView.onAdd()
AbstractView.onAdd方法源码:
onAdd : function(store, records, index) {
// 略..
nodes = me.doAdd(records, index);
// 略..
}解决办法:把Focus 处理事件,放到Store.insert();代码之后,这样调用顺序肯定是我们预期的。
‘editvoyagetask button[itemId=add]‘: {
click: function (button, e) {
var model = Ext.create(‘Soims.model.voyage.VoyageTask‘),
grid = button.up(‘panel‘),
editor;
grid.getStore().insert(0, model);
editor = grid.getCellRowEditor();
editor.startEdit(grid.getStore().getAt(0), grid.columns[0]);
}
}当然,这样的处理是违反了我们开始的初衷的。
思考:
是否需要给监听事件设置处理顺序?怎样设置?
Grid是否需要监听Store的事件,并公布接口?
本文出自 “技术人生” 博客,请务必保留此出处http://wangyuelucky.blog.51cto.com/1011508/1572211
当GridPanel添加新的条目的时候,第一个可编辑Cell自动Focus
原文地址:http://wangyuelucky.blog.51cto.com/1011508/1572211