原文:《A button in the header of an Ext JS grid action column》
在本文,将演示如何在Grid的Action列的列标题中放置按钮。
缘起
为了显示和维护大量的数据,开发人员通常会使用Grid来显示数据,并绑定一个表单来添加或编辑记录。
要实现这个,有几种做法,例如,在Grid的顶部放置一个工具条:
在这里将演示一个完全集成的UI解决方案,它会在Action列的列标题内放置一个按钮,而在改列的单元格内放置编辑和删除按钮。
问题
Ext JS的Grid列已具有通过items配置项来定义列标题的能力:
{
xtype: 'grid',
columns: [{
items: [{
xtype: 'button',
iconCls: 'x-fa fa-plus',
ui: 'default-toolbar'
}]
}, ...]
}
问题是这种方式在使用action列(xtype:’actioncolumn’)时无效。实际上,aciton列的items配置项只能用来设置单元格的图标。
{
xtype: 'grid',
columns: [{
xtype: 'actioncolumn',
items: [{
iconCls: 'x-fa fa-pencil' // config of icons in the column cells
}, {
iconCls: 'x-fa fa-trash'
}]
}, ...]
}
解决方案
使用模版列
第一个解决方案是使用模版列。模版列可以轻松的在单元格内显示Ext JS模版。
在当前情况下,使用HTML模版来显示这些图标相当的简单,而且可避免action列丢失配置项带来的麻烦:
{
xtype: 'grid',
columns: [{
xtype: 'templatecolumn',
items: [{
xtype: 'button',
iconCls: 'x-fa fa-plus',
ui: 'default-toolbar'
}],
tpl: '<span class="x-fa fa-pencil"></span><span class="x-fa fa-trash"></span>'
}]
}
不过,在每个图标上独立去处理他们的单击操作、启用或禁用操作以及提示信息,这将是比较痛苦的事情。
对于action列,是通过isActionDiasbled、handler或getTip方法来处理交互的。要在模版列实现这个,需要手动编写这些代码。
为action列创建插件
第二个解决方案是为action列创建一个插件,这更证据且更模块化。这插件的作用就是提供一种方式来配置列标题中的按钮,这样,既保留了action列的所有功能,又能获得所需的效果。
如何创建一个插件
一个扩展自Ext.AbstractPlugin
的Ext JS类:
Ext.define('MyApp.plugin.ActionColumnHeaderButtonPlugin', {
extend: 'Ext.AbstractPlugin',
alias: 'plugin.actioncolumnheaderbuttonplugin',
actionColumnHeaderId: null,
config: {
buttonConfig: null
}
定义别名是为了能方便的在列中识别插件。
在这里定义了一个属性来定位列标题内的按钮的容器。
最后,创建了一个按钮配置项来定义列标题内的按钮。
初始化
对于任何插件,可通过重写抽象方法init来获取组件并与组件实现交互。
可以通过调用set方法将插件与组件连接上:
this.setCmp(cmp);
然后,监听grid的viewready时间(在后面会讲述事件触发时会发生什么事情):
var ownerGrid = cmp.getView().ownerGrid;
ownerGrid.on('viewready', this.onViewReady, this);
然后针对列的id创建一个唯一的标识:
this.actionColumnHeaderId = cmp.getId() + '-actioncolumnheaderCt';
最后,在列标题内注入一个带有之前创建的唯一标识的HTML块,这样,就可以很容易的在插件的公共方法中来访问它。
cmp.setText('<div id="' + this.actionColumnHeaderId + '"></div>');
以下是最终完成的init方法:
init: function (cmp) {
this.setCmp(cmp);
var ownerGrid = cmp.getView().ownerGrid;
ownerGrid.on('viewready', this.onViewReady, this);
this.actionColumnHeaderId = cmp.getId() + '-actioncolumnheaderCt';
cmp.setText('<div id="' + this.actionColumnHeaderId + '"></div>');
}
在grid创建时添加按钮
Grid渲染完以后,就会触发viewready时间,就是插件监听的那个事件。当事件触发事,就可通过buttonConfig的设置来创建按钮:
var button = Ext.create('Ext.button.Button', this.getButtonConfig());
然后将这个组件注入到插件初始化时添加的容器内:
button.render(view.el.down('#' + this.actionColumnHeaderId));
完整的onViewReady方法代码如下:
onViewReady: function (view) {
var button = Ext.create('Ext.button.Button', this.getButtonConfig());
button.render(view.el.down('#' + this.actionColumnHeaderId));
}
在列中设置插件:
columns: [{
xtype: 'actioncolumn',
plugins: [{
ptype: 'actioncolumnheaderbuttonplugin',
buttonConfig: {
iconCls: 'x-fa fa-plus',
handler: 'onAddButtonClick'
}
}],
items: [{
iconCls: 'x-fa fa-pencil'
}, {
iconCls: 'x-fa fa-trash'
}]
}]
这样,就可以既使用action列的既有功能,又可以在列标题内设置一个按钮。
访问这里可以获取完整的代码以及它的结果。