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