带有可点击按钮的组合框列表

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();
        }
    }
},