Disable context menu based on data

Hey,

I want to disable the context menu based on the node data.

I am currently using:

 'contextMenuTool.showContextMenu': function (cm, obj) {
    if (obj?.part?.data?.id == 3) {
      go.ContextMenuTool.prototype.showContextMenu.call(this, cm, obj);
    } else {
      // Don't show any context menu -> Graph freezes will this block executes
    }
  },

Whenever the else block is executed the graph freezes, I also tried passing null as below
go.ContextMenuTool.prototype.showContextMenu.call(this, null, obj) even this didn’t work.
Any help here?

That code prevents the context menu from becoming visible, but the ContextMenuTool is still running.

Instead you want to prevent that tool from starting to run, by overriding the ContextMenuTool.canStart method to return false. I suggest that you first call the super method, and only if it returns true do you check for whatever you want so that you can return true or false.

Edit: Although what I wrote above is correct, in the case of context menus it is easier to override ContextMenuTool.findObjectWithContextMenu
ContextMenuTool | GoJS API
Call the super method first, and if it returns non-null, decide whether the returned GraphObject or Diagram should show its context menu and if not return null instead.

I tried overriding like below.

“contextMenuTool.findObjectWithContextMenu”: function (obj){
if (obj?.part?.data?.id == 3) {
go.ContextMenuTool.prototype.findObjectWithContextMenu.call(this, obj);
} else {
go.ContextMenuTool.prototype.findObjectWithContextMenu.call(this, null);
}
}

obj seems to be undefined. Am I doing it wrong ?

Make sure your override meets requirements of the method declaration:
ContextMenuTool | GoJS API

And I recommend that you implement what I suggested:
Call the super method first, and if it returns non-null, decide whether the returned GraphObject or Diagram should show its context menu and if not return null instead.

I think I am not able to understand this - Call the super method first

This is the working sample:

Can you please, point out how to do this?

"contextMenuTool.findObjectWithContextMenu": function(obj) {
  var result = go.ContextMenuTool.prototype.findObjectWithContextMenu.call(this, obj);
  if (result instanceof go.GraphObject && result.part.data.id !== 3) return null;
  return result;
}

Hey Walter,

A follow-up question.
The mouseDownPoint looks like it contains the previous coordinates when findObjectWithContextMenu is returned with null.
The requirement is I don’t want to show context menu for diagram, but want to publish the co-ordinates where contextmenu action occurred to the consumer ( consumer can show custom context menu based on the co-ordinates)
Any pointers?

“contextMenuTool.findObjectWithContextMenu”: function(obj) {
var result = go.ContextMenuTool.prototype.findObjectWithContextMenu.call(this, obj);
const { x, y } = self.diagram.transformDocToView(this.mouseDownPoint);
if(result instanceof go.Diagram){
self.publishContextCoordinates(x, y);
// Here x & y are not updated, it showsthe previously opened context menu co-ordinates
return null;
}else {
self.publishContextCoordinates(x, y);
// Here the x & y are proper it shows the current context menu co-ordinates
return result;
}
}

ContextMenuTool.mouseDownPoint is only valid once the tool has started running. But findObjectWithContextMenu is called from ContextMenuTool.canStart, before the tool has started.

Use Diagram.lastInput.

  this.diagram.lastInput.documentPoint