How to access node data from context menu inside node template?

Hi,

I have the following code. How do I access node data?

const contextMenuGenerator = (nodedata) => {
  switch (nodedata.type) {
    case value:
      break;

    default:
      break;
  }

  return map(menuItems,()=>{return ...})
};

const nodeTemplate = $(
  go.Node,
  'Auto',
  {
    // handle dragging a Node onto a Node to (maybe) change the reporting relationship
    mouseDragEnter: onNodeDragEnter,
    mouseDragLeave: onNodeDragLeave,
    mouseDrop: onNodeDrop,
  },
  $(
    go.Shape,
    'RoundedRectangle',
    nodeStyleDefault,
    new go.Binding('fill', 'type', changeNodeFillStyle),
    new go.Binding('stroke', 'type', changeNodeStrokeStyle),
  ),
  $(
    go.TextBlock,
    'Default Text',
    nodeTextBoxStyle,
    new go.Binding('text', 'desc').makeTwoWay(),
  ),
  {
    // define a context menu for each node
    contextMenu: $(
      go.Adornment,
      'Vertical', // that has one button
      contextMenuGenerator(nodeData),
      // more ContextMenuButtons would go here
    ), // end Adornment
  },
  $('TreeExpanderButton', nodeTreeExpanderButtonConfig),
);

Thanks,
Chat

First, I should point out that when you are building a template there is no access to any data. There can only be access to data at “run-time” for those Nodes that have been added to a Diagram by being copied from a template and then bound to some node data.

So trying to call contextMenuGenerator while you are building the GraphObject.contextMenu is far too early – there can be no nodeData at that time.

My guess is that each node data object in your model has an Array of information from which you want to build all of the context menu buttons for that particular node. Is that more-or-less correct?

If so, let’s assume that Array is the value of the “commands” property:

{
  key: ...,
  text: ...,
  commands: [
        { text: "Delete", action: "delete" },
        { text: "New Connected Node", action: "newNode" }
    ]
}

So I think your context menu should be an Adornment that binds Panel.itemArray and the Panel.itemTemplate should be a “ContextMenuButton”. Something like this:

    myDiagram.nodeTemplate =
      $(go.Node, "Auto",
        $(go.Shape,
          { fill: "white", portId: "", fromLinkable: true, toLinkable: true, cursor: "pointer" },
          new go.Binding("fill", "color")),
        $(go.TextBlock,
          { margin: 8, editable: true },
          new go.Binding("text").makeTwoWay()),
        {
          contextMenu:
            $(go.Adornment, "Vertical",
              new go.Binding("itemArray", "commands"),
              {
                itemTemplate:
                  $("ContextMenuButton",
                    $(go.TextBlock, new go.Binding("text")),
                    {
                      click: function(e, button) {
                        var cmd = button.data;
                        var nodedata = button.part.adornedPart.data;
                        console.log("On " + nodedata.text + "  " + cmd.text + ": " + cmd.action);
                      }
                    }
                  )
              }
            )
        }
      );

Then on a context click the user would see:


Your code would need to decide what to do based on the value of the `action` property.

Thank you very much Walter. I did read an older post Dynamically created Context Menu but thought I could access the data. This makes perfect sense now. Thanks,
Chat.