Javascript 在ExtJS菜单项中添加按钮

Javascript 在ExtJS菜单项中添加按钮,javascript,extjs,frontend,extjs4.2,Javascript,Extjs,Frontend,Extjs4.2,是否可以使用extjs4.2在menuitem中添加按钮 我需要做到以下几点: (在每个菜单项的复选框旁边有编辑和删除按钮。这些按钮都有自己的处理程序,单击时会打开新面板) 我试图通过为每个员工创建一个容器,并在容器中添加所需的按钮和菜单项,来实现这一点,但它无法正常工作,因为我无法单击自定义菜单项,而且设计看起来一点也不好 但是,我在下面的答案中发现了一个可能的“提示”: (但这并不完全是我所期望的,因为我不需要一个图标,我需要一个带有自己处理程序的按钮,而且我不知道与DOM交互是否是

是否可以使用
extjs4.2
menuitem
中添加
按钮

我需要做到以下几点:

(在每个
菜单项
复选框
旁边有
编辑
删除
按钮。这些按钮都有自己的处理程序,单击时会打开新面板)


我试图通过为每个
员工创建一个
容器
,并在容器中添加所需的
按钮
菜单项
,来实现这一点,但它无法正常工作,因为我无法
单击自定义
菜单项
,而且设计看起来一点也不好


但是,我在下面的答案中发现了一个可能的“提示”:

(但这并不完全是我所期望的,因为我不需要一个
图标
,我需要一个带有自己
处理程序的
按钮
,而且我不知道与
DOM
交互是否是一个很好的方法)


以下是我到目前为止得到的以及我正在进行测试的地方:

现场演示:

ExtJS代码:


如果有人知道实现此目的的“正确”方法,请让我知道,因为我不确定API中为此组件指定的配置之一是否有帮助,并且我无法在internet上找到一个好的示例:



提前感谢。

我不确定您是否有兴趣在菜单项中使用tpl:如果有,我可以改进下面的代码。和小提琴:

Ext.define('Image'){
扩展:“Ext.data.Model”,
字段:[
{name:'buttonext1',type:'string'},
{name:'buttonext2',type:'string'},
{名称:'menuText',类型:'string'}
]
});
Ext.create('Ext.data.Store'{
id:'imagesStore',
模型:“图像”,
数据:[
{buttonText1:'edit',buttonText2:'add',menuText:'Drawing',id:'1'},
{buttonText1:'edit',buttonText2:'add',menuText:'Advanced',id:'2'},
]
});
var imageTpl=new Ext.XTemplate(
'',
'',
'',
“{buttonext1}”,
“{buttonext2}{menuText}”,
'',
''
);
var dataview=Ext.create('Ext.view.view'{
itemId:'idDataView',
存储:Ext.data.StoreManager.lookup('imagesStore'),
tpl:imageTpl,
项目选择器:“div.menu-row”,
听众:{
itemclick:功能(数据视图、记录、项目){
Ext.each(项、子项、函数(项){
if(item.id=='check'+record.get('id')){
item.checked==false?item.checked=true:item.checked=false;
}
});
}
}
});
var button=Ext.create('Ext.button.Split'{
文本:“菜单按钮”,
保证金:“100”,
菜单:{
//朴素:没错,
项目:[数据视图],
听众:{
后渲染:功能(菜单){
var task=new Ext.util.DelayedTask(函数(){
Ext.each(menu.down('#idDataView').getEl().dom.children,函数(节点){
Ext.each(nodes.children,function(node){
如果(node.className=='edit'){
node.addEventListener('click',function(){
警报(“已编辑”);
});
}else if(node.className=='add'){
node.addEventListener('click',function(){
警报(“添加”);
});
}
})
});
});
任务延迟(100);
}
},
},
renderTo:Ext.getBody()
});

我可能会选择使用
容器
的方法,并尝试让它工作起来。我意识到样式可能不像框架所提供的那样好,但是经过足够的微调,您可以实现它。。。只需使用Sencha CMD、scss文件及其预定义的CSS变量

在本例中,我快速取消了按钮的列表,因此它们可以是可单击的图标/区域,我将员工记录扔到按钮本身上。。。这并不是最好的方法,但它确实有效。如果您不喜欢每个组件上的侦听器,您可以让父容器拥有侦听器,并在该函数中检查目标的CSS类。。。但这不是重点。工作:


所以你是说这样做不好?@incutonez这个解决方案看起来更好,但不知何故我觉得它太强制了,你定义自己的CSS,即使是在上面做悬停,我觉得太过分了。我宁愿尝试另一种方法,而不影响与Extjs/自定义主题一起出现的样式——我认为这是一个很好的尝试BTW(应该被视为答案,因为它符合我的期望,但我有点挑剔)。完全可以理解,但是如果您使用SENCHA CMD/SCSS文件,您就不会真正影响主题,由于添加自己的样式是有效的/您将能够使用它们的悬停颜色变量。我很喜欢Semih的方法,因为它使用了一种观点,我认为这是你唯一的另一种“正确”的方法。。。不幸的是,它使用了更多的HTML,这可能会让人毛骨悚然。@incutonez说得通,但我不想这样做
Ext.define('Namespace.view.Panel', {
    extend: 'Ext.panel.Panel',

    title: 'Panel',

    frame: true,
    floating: true,
    draggable: true,
    resizable: false,
    closable: true, 

    employees: null, 

    layout: {
        type: 'vbox',
        align: 'stretch'
    },

    constructor: function(cfg) {
        Ext.apply(this, cfg || {});

        this.items = [{
            xtype: 'container', 
            border: false,
            items: this.createItems()
        }];

        this.callParent(arguments);
    }, 

    createItems: function() {
        var items = [];

        items.push({
            xtype: 'button', 
            text: 'Employees', 
            menu: {
                xtype: 'menu', 
                items: this.createMenuItems()
            }
        });

        return items;
    }, 

    createMenuItems: function() {
        var employees = this.employees || [], 
            items = [];

        for (var i = 0; i < employees.length; ++i) {
            var employee = employees[i];
            if (employee) {
                items.push({
                    xtype: 'menucheckitem', 
                    text: Ext.String.format('{0} {1}', employee.name, employee.lastname), 
                    employeeId: employee.id, 
                    listeners: {
                        scope: this, 
                        checkchange: this.onMenuItemCheckChange
                    }
                });
            }
        }

        items.push({
            xtype: 'menuitem', 
            iconCls: 'add', 
            text: 'Add'
        });

        return items;
    }, 

    onMenuItemCheckChange: function(item, checked, eOpts) {
        console.log('Employee Id: %o was checked: %o', item.employeeId, checked);
    }, 

    destroy: function() {
        delete this.employees;

        this.callParent(arguments);
    }

});

Ext.onReady(function() {
    Ext.create('Namespace.view.Panel', {
        employees: [
            {id: 1, name: 'Oscar', lastname: 'Jara'}, 
            {id: 2, name: 'Foo', lastname: 'Bar'}
        ]
    }).show();
});
.add {
    background-image: url('http://icons.iconarchive.com/icons/awicons/vista-artistic/16/add-icon.png') !important; width: 16px; height: 16px; display: block;
}

.edit {
    background-image: url('http://icons.iconarchive.com/icons/designcontest/outline/16/Pencil-icon.png') !important; width: 16px; height: 16px; display: block;
}

.delete {
    background-image: url('http://icons.iconarchive.com/icons/oxygen-icons.org/oxygen/16/Actions-edit-delete-icon.png') !important; width: 16px; height: 16px; display: block;
}
        Ext.define('Image', {
        extend: 'Ext.data.Model',
        fields: [
            { name:'buttonText1', type:'string' },
            { name:'buttonText2', type:'string' },
            { name:'menuText',    type:'string' }
        ]
    });

    Ext.create('Ext.data.Store', {
        id:'imagesStore',
        model: 'Image',
        data: [
            { buttonText1:'edit', buttonText2: 'add', menuText:'Drawing', id: '1' },
            { buttonText1:'edit', buttonText2: 'add', menuText:'Advanced', id: '2' },
        ]
    });

    var imageTpl = new Ext.XTemplate(
            '<tpl for="."><table>',
            '<div class="menu-row">',
            '<input type="checkbox" id="check{id}">',
            '<button class="{buttonText1}">{buttonText1}</button>',
            '<button class="{buttonText2}" >{buttonText2}</button> {menuText}',
            '</div>',
            '<table></tpl>'
    );

    var dataview = Ext.create('Ext.view.View', {
            itemId: 'idDataView',
            store: Ext.data.StoreManager.lookup('imagesStore'),
            tpl: imageTpl,
            itemSelector: 'div.menu-row',
            listeners: {
                itemclick: function(dataview, record,items) {
                    Ext.each(items.children, function(item) {
                        if (item.id == 'check'+ record.get('id')) {
                            item.checked == false ? item.checked = true : item.checked = false;
                        }
                    });

                }
            }
    });

    var button = Ext.create('Ext.button.Split', {
                text: 'menuButton',
                margin: '100 100 100 100',
                menu: {
                    //plain: true,
                    items: [dataview],

                    listeners: {
                        afterrender: function(menu) {
                            var task = new Ext.util.DelayedTask(function(){
                                Ext.each(menu.down('#idDataView').getEl().dom.children, function(nodes) {
                                    Ext.each(nodes.children, function(node) {
                                        if (node.className == 'edit') {
                                            node.addEventListener('click', function() {
                                               alert('edited'); 
                                            });
                                        } else if (node.className == 'add') {
                                            node.addEventListener('click', function() {
                                               alert('added'); 
                                            });
                                        }
                                    })

                                });
                             });
                            task.delay(100);  
                        }
                    },
                },
        renderTo: Ext.getBody()

    });
Ext.application({
  name: 'Fiddle',

  launch: function() {
    Ext.define('MyPanel', {
      extend: 'Ext.panel.Panel',
      title: 'My Panel',
      renderTo: Ext.getBody(),
      employees: [{
        id: 1,
        name: 'Oscar',
        lastname: 'Jara'
      }, {
        id: 2,
        name: 'Foo',
        lastname: 'Bar'
      }],
      initComponent: function() {
        this.createMenuItems();
        this.callParent();
      },
      createMenuItems: function() {
        var items = [];
        var employees = this.employees;
        if (employees) {
          for (var i = 0; i < employees.length; i++) {
            var employee = employees[i];
            var containerItems = [];
            var checkboxCmp = Ext.create('Ext.form.field.Checkbox', {
              width: 20
            });
            containerItems.push(checkboxCmp);
            containerItems.push({
              xtype: 'button',
              cls: 'my-custom-button',
              employee: employee,
              width: 22,
              text: '',
              iconCls: 'edit',
              listeners: {
                click: this.onClickEditButton
              }
            });
            containerItems.push({
              xtype: 'button',
              cls: 'my-custom-button',
              employee: employee,
              width: 22,
              text: '',
              iconCls: 'delete',
              listeners: {
                click: this.onClickDeleteButton
              }
            });
            containerItems.push({
              xtype: 'component',
              html: '<div style="border-left:1px solid #000;height:100%; display: inline-block;"></div>'
            });
            containerItems.push({
              xtype: 'button',
              cls: 'my-custom-button',
              textAlign: 'left',
              checkboxCmp: checkboxCmp,
              employee: employee,
              flex: 1,
              text: employee.name + ' ' + employee.lastname,
              listeners: {
                click: this.onClickEmployee
              }
            });
            items.push({
              xtype: 'container',
              layout: {
                type: 'hbox',
                align: 'stretch'
              },
              overCls: 'over-item-cls',
              items: containerItems
            });
          }
        }
        this.tools = [{
          xtype: 'button',
          text: 'Employees',
          menu: {
            xtype: 'menu',
            items: items,
            plain: true
          }
        }];
      },
      onClickDeleteButton: function(button, event, eOpts) {
        alert('clicked delete, check console for employee');
        console.log('delete', button.employee);
      },
      onClickEditButton: function(button, event, eOpts) {
        alert('clicked edit, check console for employee');
        console.log('edit', button.employee);
      },
      onClickEmployee: function(button, event, eOpts) {
        alert('employee checkbox changed, check console for employee');
        console.log('employee', button.employee);
        var checkboxCmp = button.checkboxCmp;
        if (checkboxCmp) {
          checkboxCmp.setValue(!checkboxCmp.getValue());
        }

      }
    });
    Ext.create('MyPanel');
  }
});
.add {
    background-image: url('http://icons.iconarchive.com/icons/awicons/vista-artistic/16/add-icon.png') !important; width: 16px; height: 16px; display: block;
}

.edit {
    opacity: 0.4;
    background-image: url('http://icons.iconarchive.com/icons/designcontest/outline/16/Pencil-icon.png') !important; width: 16px; height: 16px; display: block;
}

.edit:hover,
.delete:hover {
    opacity: 1.0;
}

.delete {
    opacity: 0.4;
    background-image: url('http://icons.iconarchive.com/icons/oxygen-icons.org/oxygen/16/Actions-edit-delete-icon.png') !important; width: 16px; height: 16px; display: block;
}

.over-item-cls {
    background-color: lightblue;
}

a.my-custom-button.x-btn-default-small {
    background: none;
    border: none;
}

a.my-custom-button.x-btn-default-small span {
    color: #ababab;
}

a.my-custom-button.x-btn-default-small:hover span {
    color: black;
}