带有可点击按钮的组合框列表
Combobox list with clickable button
我正在尝试创建一个带有下拉菜单和可点击按钮的组合框。
我已经覆盖了 renderTpl
并复制了日期选择器 todayBtn 的按钮实例化代码。 This fiddle shows what I have now,按钮已呈现但尚未可点击,未执行处理程序。
我错过了什么?
代码:
Ext.define('EnhancedCombo', {
extend: 'Ext.form.field.ComboBox',
xtype: 'enhancedcombo',
footerButtonUI: 'default',
selAllText: 'Select All',
initComponent: function() {
var me = this;
me.callParent(arguments);
me.selAllBtn = new Ext.button.Button({
ui: me.footerButtonUI,
ownerCt: me,
ownerLayout: me.getComponentLayout(),
text: me.selAllText,
tabIndex: -1,
ariaRole: 'presentation',
handler: me.selectAll,
scope: me
});
},
listConfig: {
renderTpl: [
'<div id="{id}-listWrap" data-ref="listWrap"',
' class="{baseCls}-list-ct ', Ext.dom.Element.unselectableCls, '">',
'<ul id="{id}-listEl" data-ref="listEl" class="', Ext.baseCSSPrefix, 'list-plain"',
'<tpl foreach="ariaAttributes"> {$}="{.}"</tpl>',
'>',
'</ul>',
'</div>',
'<div id="{id}-footerEl" data-ref="footerEl" role="presentation" class="{baseCls}-footer" style="">{%this.renderSelAllBtn(values, out)%}</div>',
{
disableFormats: true,
renderSelAllBtn: function(values, out) {
Ext.DomHelper.generateMarkup(values.$comp.ownerCmp.selAllBtn.getRenderTree(), out);
}
}
],
},
selectAll: function() {
console.log('select all');
this.getPicker().getSelectionModel().selectAll();
}
});
由于您正在使用 Ext.DomHelper.generateMarkup()
,因此它将 return html 以 Array
的形式出现。所以你只是附加了那个按钮的 html 而不是组件。
您可以实现此功能,您需要像这样在 picker
上使用 addListener
方法
picker.addListener('afterrender', function(){},scop);
然后,在 afterrender
事件中,您可以通过使用 Ext.dom.Element.down()
获取 dom 元素来添加 click
事件
picker.addListener('afterrender', (comp) => comp.el.down('.selectall').on('click', this.selectAll, comp), me)
FIDDLE
在上面fiddle,我创建了一个演示。
代码片段
Ext.application({
name: 'Fiddle',
launch: function () {
var btn = new Ext.button.Button({
text: 'Working button',
handler: function () {
alert('Working button click');
},
listeners: {
afterrender: function () {
console.log('afterrender Working button')
}
}
});
function getBtnHtml() {
let button = new Ext.button.Button({
text: 'No wokring button',
handler: function () {
alert('Test 2');
},
listeners: {
afterrender: function () {
console.log('afterrender not Working button')
}
}
});
return Ext.DomHelper.generateMarkup(button.getRenderTree(), []).join('')
}
Ext.create({
xtype: 'panel',
title: 'Demo',
renderTo: Ext.getBody(),
layout: 'hbox',
defaults: {
flex: 1,
margin: 10
},
items: [btn, {
xtype: 'panel',
html: getBtnHtml()
}]
})
Ext.define('EnhancedCombo', {
extend: 'Ext.form.field.ComboBox',
xtype: 'enhancedcombo',
footerButtonUI: 'default',
selAllText: 'Select All',
multiSelect: true,
initComponent: function () {
this.callParent(arguments);
var me = this,
picker = me.getPicker();
me.selAllBtn = new Ext.button.Button({
ui: me.footerButtonUI,
ownerCt: me,
ownerLayout: picker.getComponentLayout(),
text: me.selAllText,
cls: 'selectall',
tabIndex: -1,
ariaRole: 'presentation',
scope: me
});
picker.addListener('afterrender', (comp) => comp.el.down('.selectall').on('click', this.selectAll, comp), me);
},
listConfig: {
renderTpl: [
'<div id="{id}-listWrap" data-ref="listWrap"',
' class="{baseCls}-list-ct ', Ext.dom.Element.unselectableCls, '">',
'<ul id="{id}-listEl" data-ref="listEl" class="', Ext.baseCSSPrefix, 'list-plain"',
'<tpl foreach="ariaAttributes"> {$}="{.}"</tpl>',
'>',
'</ul>',
'</div>',
'<div id="{id}-footerEl" data-ref="footerEl" role="presentation" class="{baseCls}-footer" style="">{%this.renderSelAllBtn(values, out)%}</div>', {
disableFormats: true,
renderSelAllBtn: function (values, out) {
Ext.DomHelper.generateMarkup(values.$comp.ownerCmp.selAllBtn.getRenderTree(), out);
}
}
],
},
selectAll: function () {
console.log('select all');
this.getSelectionModel().selectAll();
}
});
Ext.create('EnhancedCombo', {
renderTo: Ext.getBody(),
store: ['Test 1', 'Test 2']
}).expand();
}
});
每个组件都有一个方法 finishRender
,它在渲染期间从父组件调用 运行。当我通过 generateMarkup
手动生成标记时,我还必须在选择器呈现后手动调用 finishRender
方法才能单击按钮。
在 DatePicker 中,todayBtn 的 finishRender
是从覆盖的私有 finishRenderChildren
方法中调用的。虽然我无法覆盖我的选择器的私有方法,但我可以从我可以添加到选择器的 afterrender
侦听器调用相同的 finishRender
方法(如 Narendra Jadhav 所建议的):
listConfig: {
...
listeners: {
afterrender: function(picker) {
picker.ownerCmp.selAllBtn.finishRender();
}
}
},
我正在尝试创建一个带有下拉菜单和可点击按钮的组合框。
我已经覆盖了 renderTpl
并复制了日期选择器 todayBtn 的按钮实例化代码。 This fiddle shows what I have now,按钮已呈现但尚未可点击,未执行处理程序。
我错过了什么?
代码:
Ext.define('EnhancedCombo', {
extend: 'Ext.form.field.ComboBox',
xtype: 'enhancedcombo',
footerButtonUI: 'default',
selAllText: 'Select All',
initComponent: function() {
var me = this;
me.callParent(arguments);
me.selAllBtn = new Ext.button.Button({
ui: me.footerButtonUI,
ownerCt: me,
ownerLayout: me.getComponentLayout(),
text: me.selAllText,
tabIndex: -1,
ariaRole: 'presentation',
handler: me.selectAll,
scope: me
});
},
listConfig: {
renderTpl: [
'<div id="{id}-listWrap" data-ref="listWrap"',
' class="{baseCls}-list-ct ', Ext.dom.Element.unselectableCls, '">',
'<ul id="{id}-listEl" data-ref="listEl" class="', Ext.baseCSSPrefix, 'list-plain"',
'<tpl foreach="ariaAttributes"> {$}="{.}"</tpl>',
'>',
'</ul>',
'</div>',
'<div id="{id}-footerEl" data-ref="footerEl" role="presentation" class="{baseCls}-footer" style="">{%this.renderSelAllBtn(values, out)%}</div>',
{
disableFormats: true,
renderSelAllBtn: function(values, out) {
Ext.DomHelper.generateMarkup(values.$comp.ownerCmp.selAllBtn.getRenderTree(), out);
}
}
],
},
selectAll: function() {
console.log('select all');
this.getPicker().getSelectionModel().selectAll();
}
});
由于您正在使用 Ext.DomHelper.generateMarkup()
,因此它将 return html 以 Array
的形式出现。所以你只是附加了那个按钮的 html 而不是组件。
您可以实现此功能,您需要像这样在 picker
上使用 addListener
方法
picker.addListener('afterrender', function(){},scop);
然后,在 afterrender
事件中,您可以通过使用 Ext.dom.Element.down()
获取 dom 元素来添加 click
事件
picker.addListener('afterrender', (comp) => comp.el.down('.selectall').on('click', this.selectAll, comp), me)
FIDDLE
在上面fiddle,我创建了一个演示。
代码片段
Ext.application({
name: 'Fiddle',
launch: function () {
var btn = new Ext.button.Button({
text: 'Working button',
handler: function () {
alert('Working button click');
},
listeners: {
afterrender: function () {
console.log('afterrender Working button')
}
}
});
function getBtnHtml() {
let button = new Ext.button.Button({
text: 'No wokring button',
handler: function () {
alert('Test 2');
},
listeners: {
afterrender: function () {
console.log('afterrender not Working button')
}
}
});
return Ext.DomHelper.generateMarkup(button.getRenderTree(), []).join('')
}
Ext.create({
xtype: 'panel',
title: 'Demo',
renderTo: Ext.getBody(),
layout: 'hbox',
defaults: {
flex: 1,
margin: 10
},
items: [btn, {
xtype: 'panel',
html: getBtnHtml()
}]
})
Ext.define('EnhancedCombo', {
extend: 'Ext.form.field.ComboBox',
xtype: 'enhancedcombo',
footerButtonUI: 'default',
selAllText: 'Select All',
multiSelect: true,
initComponent: function () {
this.callParent(arguments);
var me = this,
picker = me.getPicker();
me.selAllBtn = new Ext.button.Button({
ui: me.footerButtonUI,
ownerCt: me,
ownerLayout: picker.getComponentLayout(),
text: me.selAllText,
cls: 'selectall',
tabIndex: -1,
ariaRole: 'presentation',
scope: me
});
picker.addListener('afterrender', (comp) => comp.el.down('.selectall').on('click', this.selectAll, comp), me);
},
listConfig: {
renderTpl: [
'<div id="{id}-listWrap" data-ref="listWrap"',
' class="{baseCls}-list-ct ', Ext.dom.Element.unselectableCls, '">',
'<ul id="{id}-listEl" data-ref="listEl" class="', Ext.baseCSSPrefix, 'list-plain"',
'<tpl foreach="ariaAttributes"> {$}="{.}"</tpl>',
'>',
'</ul>',
'</div>',
'<div id="{id}-footerEl" data-ref="footerEl" role="presentation" class="{baseCls}-footer" style="">{%this.renderSelAllBtn(values, out)%}</div>', {
disableFormats: true,
renderSelAllBtn: function (values, out) {
Ext.DomHelper.generateMarkup(values.$comp.ownerCmp.selAllBtn.getRenderTree(), out);
}
}
],
},
selectAll: function () {
console.log('select all');
this.getSelectionModel().selectAll();
}
});
Ext.create('EnhancedCombo', {
renderTo: Ext.getBody(),
store: ['Test 1', 'Test 2']
}).expand();
}
});
每个组件都有一个方法 finishRender
,它在渲染期间从父组件调用 运行。当我通过 generateMarkup
手动生成标记时,我还必须在选择器呈现后手动调用 finishRender
方法才能单击按钮。
在 DatePicker 中,todayBtn 的 finishRender
是从覆盖的私有 finishRenderChildren
方法中调用的。虽然我无法覆盖我的选择器的私有方法,但我可以从我可以添加到选择器的 afterrender
侦听器调用相同的 finishRender
方法(如 Narendra Jadhav 所建议的):
listConfig: {
...
listeners: {
afterrender: function(picker) {
picker.ownerCmp.selAllBtn.finishRender();
}
}
},