ExtJs bubble menu event - extjs

I have my ExtJs menu defined as follows. I have two custom methods added to my menu item 'hookMethod' and 'handlerMethod'. 'hookMethod' is added based upon some condition. I bubble the click event for individual menu items to the root menu.
Then checks if hook is defined then call 'hookMethod' else call the 'handlerMethod' directly. The problem that I am facing is that the click listener is called twice, once for menuitem and once for menu. Also, what is e argument. I was thinking it will be called only once for menu and I will have some way to retrieve the actual menu item being clicked in it.
{
xtype: "menu",
listeners: {
click: function(item, e, eopts)
{
if(item.hookMethod) {
item.hookMethod(item.handlerMethod);
}
else {
item.handlerMethod(this);
}
}
},
items: [{
xtype: "menuitem",
text: "Process Record",
bubbleEvents: ['click'],
hookMethod: function(actualMethod)
{
//do some pre-processing here and then call the actual handler
actualMethod(args)
},
handlerMethod: function(args)
{
//Do actual processing
},
}]
}

Ext.menu.Menu click( menu, item, e, eOpts ) event have four parameters.
First parameter is menu object itself.
Second item parameter is object of the menu item that was clicked. This parameter you can use for determine which item in menu was clicked.

Related

ExtJs : Container must not receive child item's click events and Process only events on container

I want to process mouse up/down events in the empty area(marked in color) which belongs to container.
As shown in the picture, container has menu bar to the left and window standard buttons to the right. Expected behavior is : click on menu items/buttons must trigger their event handlers and click on empty area(marked in color) must be processed by container to support window drag.
I tried this in container:
listeners: {
mousedown: {
fn: function() {
_mousepressed = true;
},
element: 'el'
},
mouseup: {
fn: function() {
_mousepressed = false;
},
element: 'el'
},
When clicked on menu item button, the event is first coming to container's mouseup handler and then button handler is called. Instead , I expect not to receive event in container when child items are clicked. I need clicks on empty areas in container.
Is there any extjs way to identify events on parent container and not on its chid items?

Adding enabling and disabling as context menu on a grid in extjs

Hi I have added one context menu on my grid which will perform the enable and disable functionality for selected row. I am new to ExtJs. I have added below listener for the grid. How to add enable and disable functionality for the grid row?
listeners: {
itemcontextmenu: function (grid, record, item, index, e) {
var contextMenu = Ext.create('Ext.menu.Menu', {
controller: 'grid-controller',
width: 165,
plain: true,
items: [{
text: 'Disable',
listeners: {
click: {fn: 'disable', extra: record}
},
}]
});
e.stopEvent();
contextMenu.showAt(e.getXY());
}
}
This is not a copy-paste answer, but going through the following steps with doing your own research you can solve your problem.
1. Create the context menu only once and destroy it
In you code, the context menu is created every time when the user opens up the menu on the grid. This is not good. Instead, create the context menu only once when the grid is created, and destroy it when the grid is destroyed. Something like this:
Ext.define('MyGrid', {
extend: 'Ext.grid.Panel',
initComponent : function() {
this.callParent();
this.MyMenu = Ext.create('Ext.menu.Menu', {
items: [...]
});
this.on({
scope : this,
itemcontextmenu : this.onItemContextMenu
});
},
onDestroy : function() {
if (this.MyMenu) {
this.MyMenu.destroy();
}
},
onItemContextMenu : function(view, rec, item,index, event) {
event.stopEvent();
this.MyMenu.showAt(event.getXY());
}
});
2. Store enabled / disabled state in the record
For the next step to work, records in your grid must contain whether the corresponding row is enabled or disabled. In the context menu, when user selects enabled / disabled, store this status like this, get record of the row where the context menu was displayed from:
record.set('myDisabledState', true); // or false
It is important to store the disabled state (and not enabled), because when your grid initially is rendered, these values won't be in the records, so record.get('myDisabledState') will evaluate to FALSE, and that is the desired behaviour, if you want to start with every row being able to be selected.
3. Disable selection
Now you can add a beforeselect listener to your grid, see documentation. This listeners receives record as parameter, and if you return false from this listener, the selection will be canceled. So in this listener simply add:
listeners: {
beforeselect: function ( grid, record, index, eOpts ) {
return !record.get('myDisabledState');
}
}
4. Apply formatting - OPTIONAL
It is likely that you want to add different formatting for disabled rows, for example grey colour. The easiest way to do it is to add a custom CSS style to your Application.scss file:
.my-disabled-row .x-grid-cell-inner {
color: gray;
}
Finally add getRowClass configuration to your grid, it will receive the current record being rendered, and you can return the above custom CSS style when the row is disabled:
Ext.define('MyGrid', {
// your grid definition
,
viewConfig: {
getRowClass: function (record, rowIndex, rowParams, store) {
if (record.get('myDisabledState')) {
return "my-disabled-row";
}
}
}
});
In this last part, when row is not disabled, it will return nothing, so default formatting will be used.

Context menu in grid in ExtJS

I have a two context menu items inside my grid. The first one is "delete" and the second one is Disable or Enable. Delete context menu I have added as below
var contextMenu = Ext.create('Ext.menu.Menu', {
controller: 'sites',
width: 250,
plain: true,
items: [{
text: 'Delete',
handler: function () {
},
}]
Now I wanted to add Disable or Enable inside the items as a context menu. By enable or disable I mean I need to check the state of that particular row of the grid i.e. if the state of the row is enabled then "Disable" option should be come in the context menu and if the state is disables then the "Enable" option should be come in the context menu. How can I check the state of the row and how can I put if else condition inside my items? Below is the column for checking the enabling of the row.
columns: [
{text:'Active',dataIndex:'enabled',flex:1 },
]
You can use an actioncolumn to do so. It renders an icon in the grid cell, where you can link a function thanks to the handler config.
Here you can check with the record parameter whether the selected row is active, and render conditionally the right option; for example:
handler: function(view, rowIndex, colIndex, item, e, record, eOpts) {
if (record.data.active) {
openDisableMenu()
} else {
openEnableMenu()
}
}

ExtJS: keyboard focus specific context menu item

Currently I'm opening a context menu following the strike of a keyboard shortcut.
How do I focus on (and select/highlight) a particular menu item of the context menu? So that then the item's handler can be executed by hitting the return key. I'm running ExtJS 4.1.
This what I'm currently doing:
myMenu.showBy(divElement); // divElement is a DOM object
myMenu.items.items[2].focus(); // focus on 3rd menu item
myMenu.doConstrain(); // move floating component into a constrain region
Still, focus is maintained on the menu element itself.
A look into the source reveals that this is done using the setActiveItem() method:
var the_menu = Ext.create('Ext.menu.Menu', {
items: [
{
itemId: 'foo',
text: 'Foo'
},
{
itemId: 'bar',
text: 'Bar'
}
]
}).showBy(document.getElementById('some_div'));
the_menu.setActiveItem(the_menu.down('#bar'));
Note that this method is private, however canActivateItem(item) and deactivateActiveItem(andBlurFocusedItem) are public, so it's probably just an oversight.

Context menu within a menu item in ExtJS

I have a Menu that contains a TreePanel. The users need to be able to interact with a the TreePanel's nodes using a context menu. I'm showing the context menu from a function attached to the TreePanel's contextmenu event.
This works except:
Without allowOtherMenus: true, showing the context menu causes the main menu, and therefore the TreePanel, to disappear ;
With allowOtherMenus: true on either menu, the context menu doesn't disappear when the users clicks a blank area of the TreePanel.
I'm looking for a way to have the context menu to work as if the TreePanel were not an item within a menu.
Mockup :
I found this that seems to work on FF3/IE8/Chrome, although it could have side effects that have not shown up yet.
var hide_context_menu = function () { context_menu.hide() };
var context_menu = new Ext.menu.Menu({
allowOtherMenus: true,
items: [...],
listeners: {
show: function () {
Ext.getDoc().on('mouseup', hide_context_menu);
},
hide: function () {
Ext.getDoc().un('mouseup', hide_context_menu);
}
}
});
allowOtherMenus: true prevents the hiding of the main menu by the MenuMgr when the context menu pops up. Hiding the handler to the mouseup event allows for click events to be processed.

Resources