Displaying Menu On Context Menu Extjs

2.9k Views Asked by At

Up until 6.2, context menu on a grid worked fine by doing

itemcontextmenu: function (a,b,c,d, e) { 
  contextmenu.showAt(e.getXY()); 
}

But with 6.5, the menu doesn't show at the given XY coordinate if the menu is shown outside of the context menu. I have included an example below. Anyone seen this issue? I have tried turning on the animation option too, but the menu doesn't constrain within the panel, so when you right click at the bottom of the grid, the menu shows at the bottom below the panel.

Any input is highly appreciated

Working example

  1. Right click on any grid row

  2. Context Menu shows where you clicked.

Non-working example

  1. Click on the Menu Button (menu shows below the button)

  2. Right click on any grid row

  3. Context menu shows where it was displayed below Menu Button instead of where you clicked.

var mymenu = new Ext.menu.Menu({
        items: [
            // these will render as dropdown menu items when the arrow is clicked:
            {text: 'Item 1', handler: function(){ alert("Item 1 clicked"); }},
            {text: 'Item 2', handler: function(){ alert("Item 2 clicked"); }}
        ]
    });
Ext.create('Ext.button.Split', {
    renderTo: Ext.getBody(),
    text: 'Menu Button',
    menu: mymenu
});
Ext.create('Ext.data.Store', {
    storeId: 'simpsonsStore',
    fields:[ 'name', 'email', 'phone'],
    data: [
        { name: 'Lisa', email: '[email protected]', phone: '555-111-1224' },
        { name: 'Bart', email: '[email protected]', phone: '555-222-1234' },
        { name: 'Homer', email: '[email protected]', phone: '555-222-1244' },
        { name: 'Marge', email: '[email protected]', phone: '555-222-1254' }
    ]
});
Ext.create('Ext.grid.Panel', {
    title: 'Simpsons',
    store: Ext.data.StoreManager.lookup('simpsonsStore'),
    columns: [
        { text: 'Name', dataIndex: 'name' },
        { text: 'Email', dataIndex: 'email', flex: 1 },
        { text: 'Phone', dataIndex: 'phone' }
    ],
    height: 200,
    width: 400,
    renderTo: Ext.getBody(),
    listeners: {
        scope: this,
        itemcontextmenu: function (a,b,c,d,e){
            e.stopEvent();
            mymenu.showAt(e.getXY());
        }
        
    }
    
});

2

There are 2 best solutions below

0
bakamike On

I made a fiddle in 6.2 and it has the exact same behaviour as 6.5

https://fiddle.sencha.com/#view/editor&fiddle/23kn

The issue is you are assigning the same menu for context menus to the split button. You would need to destroy and recreate the menu each time. Also as a side note you should cache the context menu on the grid otherwise every time you right-click you are creating a new menu and the old one still remains...big memory leak.

5
Ajay Thakur On

You can prevent memory leak like this.

new Ext.grid.Panel({
    plugins: 'viewport',
    title: 'Users',
    dockedItems: [{
        xtype: 'toolbar',
        dock: 'top',
        items: [{
            xtype: 'splitbutton',
            text: 'menu',
            menu: mymenu
        }]
    }],
    store: {
        data: [{
            name: 'Lisa',
            email: '[email protected]',
            phone: '555-111-1224'
        }, {
            name: 'Bart',
            email: '[email protected]',
            phone: '555-222-1234'
        }, {
            name: 'Homer',
            email: '[email protected]',
            phone: '555-222-1244'
        }, {
            name: 'Marge',
            email: '[email protected]',
            phone: '555-222-1254'
        }]
    },
    columns: [{
        text: 'Name',
        dataIndex: 'name'
    }, {
        text: 'Email',
        dataIndex: 'email',
        flex: 1
    }, {
        text: 'Phone',
        dataIndex: 'phone'
    }],
    height: 200,
    width: 400,
    listeners: {
        scope: this,
        itemcontextmenu: function (a, b, c, d, e) {
            e.stopEvent();
            var mymenu = new Ext.menu.Menu({
               items: [
                 {
                     text: 'Item 1',
                     handler: function () {
                         alert("Item 1 clicked");
                      }
                 }, {
                       text: 'Item 2',
                       handler: function () {
                           alert("Item 2 clicked");
                       }
                }
             ],
             listeners:{
                 hide:function(){
                    setTimeout(function(){
                        mymenu.destroy();
                    },2000);
                }
             }
            });
            mymenu.showAt(e.getXY());
        }
    }
});