In this article I will discuss and demonstrate how to create a context menu so that when a user right clicks on grid they are able to take action.
EXTJS in XPages series
Here are links to all of the previous articles in this series
- EXTJS in XPages #15 – Multi-select of documents
- EXTJS in XPages #14 – Grid editing and saving data via REST CRUD
- EXTJS in XPages #13: Totaling your columns with a groupingSummary
- EXTJS in XPages #12 – Counting categories with Grouped columns
- EXTJS in XPages #11 – Grids with Locked Column(s)
- EXTJS in XPages #10 – Grid Row Expander plugin
- EXTJS in XPages #9 – Infinite scrolling rebooted and reborn – v4.2 BufferedRenderer
- EXTJS in XPages #8 – Selecting data from the grid and opening a document
- EXTJS in XPages #7 – Doing an @Unique(@DbColumn) equivalent in the grid
- EXTJS in XPages #6 – remote sorting using the REST service
- EXTJS in XPages #5 – Infinite scroller
- EXTJS in XPages #4 – Adding a Pager
- EXTJS in XPages #3 – Creating a basic grid from a Custom Control
- EXTJS in XPages #2 – Basic Grid capabilities
- EXTJS in XPages #1 – Starting from scratch (the first grid)
Demonstration
The EXTJS in XPages demonstration database can be found at http://demo.xomino.com/xomino/Extjs.nsf/xBufferedRendererContextMenu.xsp
Download
The sample database that will accompany this series is available from the menu in the live demo database from this link – http://demo.xomino.com/xomino/Extjs.nsf
Introduction
Context menus (right click menu) are one form of user experience which “reduces clicks”. But that is a fallacy in some senses because the user is not clicking any less they are just less annoyed by the clicks 🙂
If the user is in a grid and has to select some documents, then move their mouse out of the grid and click an “Approve” button that is “one click” but “with an annoying mouse movement”. Right click – select Approve is actually two clicks…..which is more clicks but is less annoying because of little to no mouse movement.
How does that work?
In the grid we are able to create a context menu by “Creating a menu” and “adding it to the onContextMenu event of the grid view. In the example below I am creating the “approveAction”. In that action we:
- define the icon which will appear int he menu
- define the text on the menu action
- have a handler which interprets what happens when the menu action is clicked
- In this case the action gets all the selected documents and creates a JSON string from it
- That JSON string is then shown on the console for debugging
var approveAction = Ext.create('Ext.Action', { icon : 'images/add.png', // Use a URL in the icon config text: 'Approve Users', disabled: false, handler: function(widget, event) { var selection = Ext.getCmp('myPanel').getSelectionModel().getSelection(); var theJSON=[] for ( var i = 0; i < selection.length; i++) { theJSON.push({'unid': selection[i].data["@unid"], 'field': 'status', 'val': 'approved'} ) } console.dir(theJSON) } })
I will get to writing about how to do the update like I promised……but suffice to say that this is posted at a customREST control which will then update the values based on the UNID.
The menu is added to the grid in the following manner. A view listener is added to the grid and in the itemcontextmenu event we detect where the event is happening and then display the menu at exactly that point (you could offset this if you wanted)
The menu is smart enough that if you do not click on the menu itself it disappears when you click away from it.
gridFunc = { self: this, grid: function(){ return Ext.getCmp('myPanel') }, contextMenu: Ext.create('Ext.menu.Menu', { items: [ approveAction, rejectAction ] }) } var grid = Ext.create('Ext.grid.Panel', { viewConfig: { stripeRows: true, listeners: { itemcontextmenu: function(view, rec, node, index, e) { e.stopEvent(); gridFunc.contextMenu.showAt(e.getXY()); return false; } } }, etc
Reusing the actions
Not only can the actions be added to the context menu, but because they are created as EXT Objects they can be added to other place as well – like a toolbar
gridDock = [{ id: 'activeStorePaging', xtype: 'toolbar', dock: 'bottom', items: [ { text: 'Clear Filter Data', handler: function () { grid.filters.clearFilters(); } }, '-', approveAction, '-', rejectAction ] }]
Conclusion
As you can see with great control and little additional effort (as ever!) we are able to add more feature rich functionality to our grid