How do you refresh a dijit menu's menuitems?

1680
2
Jump to solution
04-24-2017 10:40 AM
GregRieck
Occasional Contributor III

Here is a link that shows the issue: JS Bin - Collaborative JavaScript Debugging 

When you right click A nothing happens, right click A a second time and the menu appears. OR right click A and then right click B and the menu appears with A's content. I'm simply trying to get the context menu to appear the first time and be specific to the selected row. You right click A you get A's context menu, you right click B you get B's context menu. And always on the first click.

Hello, I'm trying to make the dijit menu's menuitems custom to the item selected in a dgrid row.

Right now the menuitems aren't refreshing when the row changes.

For example if the first row I click on is "C" I get:

First, C1, C2, Last - correct!

If I then right click on row B I get the same thing as above for C.

BUT!, If I then click back onto row C I get:

First, B, Last - incorrect - This is what should have been displayed on the B row click just above.

If I then re-click on row C the menu items are correct. Or if I were to right click twice on any row the second menu items list is correct.

I'm trying to customize the menu items to the row being selected. How can I "refresh", "clear", "reset" whatever so that the menuitems will be specific to the row being selected?

Also, I'm having a problem where I have to right click twice in order to display the context menu. I think it has something to do with my "targetNodeIds" - var pmenu = new Menu({ targetNodeIds: [thisRoot.grid.domNode] });

"thisRoot" is the "window.this", the dgrid scope this.

this.grid.on('.dgrid-row:contextmenu', function (evt) {
evt.preventDefault();
if (selectedRow != null && selectedRow.XObject1 != null) {
   var pmenu = new Menu({ targetNodeIds: [thisRoot.grid.domNode] });
   pmenu.addChild(new MenuItem({
      label: "AlwaysFirstItemInTheList",
      iconClass: "FIRST",
      onClick: function () { contextFunc(this.id, selectedRow); }
   }));
   switch (selectedRow.XObject1.XTypeTable) {
      case "A":
         break;
       case "B":
            pmenu.addChild(new MenuItem({
              label: "B",
              iconClass: "B",
              onClick: function () { contextFunc(this.id, selectedRow); }
            }));
            break;
       case "C":
          pmenu.addChild(new MenuItem({
            label: "C1",
            iconClass: "C",
            onClick: function () { contextFunc(this.id, selectedRow); }
          }));
          pmenu.addChild(new MenuItem({
               label: "C2",
               iconClass: "C",
               onClick: function () { contextFunc(this.id, selectedRow); }
            }));
            break;
   }
   pmenu.addChild(new MenuItem({
     label: "AlwaysLastItemInTheList",
     onClick: function () { contextFunc(this.id, selectedRow); }
   }));
   pmenu.startup();

0 Kudos
1 Solution

Accepted Solutions
GregRieck
Occasional Contributor III

So this is what I ended up doing that resolved this issue for me. Instead of using a row context menu event I changed to a row mousedown event. Then I checked if the mouse down was the right button and added my code inside that block. This works as expected. Note that now that you build a new context menu every time you right click on a row, you may want to destroy the previous menu before creating a new one. What I am doing is keeping the previous menu if it does not change, and destroying previous if I need to create a new one (theMenu.destroyRecursive()).

grid.on(".dgrid-row:mousedown, mouseDownCallback);

mouseDownCallback: function(evt) {
  var row = grid.row(evt);
  if (mouse.isRight(evt)) {

    //here build your context menu depending on the content of row, for example the following will show a context menu         //with one item which when clicked will popup an alert box with the content of the row's name property value:
    var theMenu = new Menu({targetNodeIds: [grid.domNode], selector: ".dgrid-row"});
    theMenu.addChild(new MenuItem({label: row.name, onClick: function(evt){alert('name: ', row.name)});
  }
}

View solution in original post

0 Kudos
2 Replies
JohnGrayson
Esri Regular Contributor

A different approach is to disable menu items based on the item clicked on (my bin was messed up, so below the relevant code, including an update for hiding instead of disabling). Regarding your 'one off' issue; could it be that the store items don't have a unique id?  

var grid = new OnDemandGrid({
  store: new Memory({ data: [{ id:"A", label: "A" },{ id:"B", label: "B" }] }),
  columns: { label: "Label" }
}, "grid");
grid.startup();
 
var cellMenu = new Menu({targetNodeIds:[grid.domNode]});
var menuItemA = new MenuItem({
  label:"Label_A Menu",
  iconClass:"dijitEditorIcon dijitEditorIconCopy",
  onClick: function(){alert('A was clicked')} 
});
var menuItemB = new MenuItem({
  label:"Label_B Menu",
  iconClass:"dijitEditorIcon dijitEditorIconCut",
  onClick: function(){alert('B was clicked')}
});
cellMenu.addChild(menuItemA);
cellMenu.addChild(menuItemB);
cellMenu.startup(); 
 
grid.on(".dgrid-content .dgrid-row:contextmenu", function(evt) {
  evt.preventDefault(); 
  var row = grid.row(evt); 
  var activeItemLabel = row.data.label; 
  //menuItemA.attr("disabled",(activeItemLabel !== "A"));
  //menuItemB.attr("disabled",(activeItemLabel !== "B"));  
  domStyle.set(menuItemA.domNode, "display", (activeItemLabel !== "A") ? "none":  "inline-block");
  domStyle.set(menuItemB.domNode, "display", (activeItemLabel !== "B") ? "none" : "inline-block");    
});‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
GregRieck
Occasional Contributor III

So this is what I ended up doing that resolved this issue for me. Instead of using a row context menu event I changed to a row mousedown event. Then I checked if the mouse down was the right button and added my code inside that block. This works as expected. Note that now that you build a new context menu every time you right click on a row, you may want to destroy the previous menu before creating a new one. What I am doing is keeping the previous menu if it does not change, and destroying previous if I need to create a new one (theMenu.destroyRecursive()).

grid.on(".dgrid-row:mousedown, mouseDownCallback);

mouseDownCallback: function(evt) {
  var row = grid.row(evt);
  if (mouse.isRight(evt)) {

    //here build your context menu depending on the content of row, for example the following will show a context menu         //with one item which when clicked will popup an alert box with the content of the row's name property value:
    var theMenu = new Menu({targetNodeIds: [grid.domNode], selector: ".dgrid-row"});
    theMenu.addChild(new MenuItem({label: row.name, onClick: function(evt){alert('name: ', row.name)});
  }
}

0 Kudos