It triggers change detection on every single mousemove event on diagram

Hi, I’m using gojs on drawing a network diagram on Angular framework base project.

The problem is that it triggers change detection on every single mousemove event on diagram.
So I was wondering if there’s any way to disable mousemove event programmatically.

Thank you.

Yes there is a way to disable all mouse move events, but it seems very unlikely that you would really want to do that.

First, have you read Loop call while hovering cursor on top of canvas while integrating with angular 2 to see if that topic helps you?

That topic is exactly the issue I’m going through. About the OnPush strategy, it doesn’t work in this case because as soon as the change detection occurs from the root component and spread out to the bottom so although I set it to the diagram component, the other component will be checked. Of course I could possibly set OnPush to the root component but then I would need to add an extra code to detect the other changes in other component because of this mousemove event. So I think just disabling the mousemove event in gojs seems reasonable.

We’ll look into this issue tomorrow.

Thanks! Looking forward to your answer :)

Before we get too bogged down by dealing with Angular zones, I’d like to understand exactly what behavior it is that you want to avoid.

If you don’t want cursors or tooltips to show when the user moves the mouse without any particular tool running, you can override the methods ToolManager.standardMouseOver and ToolManager.standardWaitAfter to be no-ops. Doing so will still allow tools such as the DraggingTool or LinkingTool or PanningTool to run normally.

If you don’t want any ToolManager.mouseMoveTools tool to run, you could override ToolManager.doMouseMove to be a no-op. That would still allow tools such as the ClickSelectingTool, the ResizingTool, and the TextEditingTool to run.

But I’m not sure that such kinds of disabling mouse-move events is going to help. I assume Angular’s dirty-checking will happen with every mouse-move event, not just for some cases, so overriding the behavior to be no-ops won’t prevent that dirty-checking. I don’t think there is a reasonable way to avoid the internal call to addEventListener(…, 'mousemove', …).

First, thanks for your reply!

The problem what I want to avoid is that the continuous change detection which gets triggered by the mousemove event from the diagram. That’s it. I could possibly set other components not to get affected by the change detection the diagram triggers but in my thinking, just blocking/disabling the mousemove event itself sounds easier and reasonable instead. I just give it a try whether it works or not :)

It sounds like I need to override ToolManager.doMouseMove to be a no-op as you explained. How can I override it to be a no-op?

$(go.Diagram, . . .,
  { . . .,
    "toolManager.doMouseMove": function() {},
    . . .
  })

But as I just said above, I think it won’t help because Angular’s overriding of addEventListener is where the problem resides. So I suppose you could try overriding addEventListener to be a no-op if it’s for “mousemove”. However I’m not sure that you can do so without breaking mouse-move events for everything.

Yeah I tried it but it didn’t work :(

I suppose I need to stick with OnPush strategy for now.

Hello, I’ve been experimenting a bit with this today.

When you set your diagram’s div, that’s what adds event listeners to the canvas. So, I recommend trying to run that bit of code within an NgZone runOutsideAngular call. Read more on that here: https://angular.io/api/core/NgZone#runoutsideangular

I just tried this today and it worked alright. Here’s my code:

/**
* Constructor
*/
constructor(private _zone: NgZone) { }    

/**
* Initializes diagram / model after view init
*/
public ngAfterViewInit() {
  // this is just some function that returns a Diagram
  this.diagram = this.initDiagram();
  // this.diagramDiv is an ElementRef @Input property
  const divRef = this.diagramDiv.nativeElement;

  // here's where the magic happens
  this._zone.runOutsideAngular(() => {
    // Here is where the diagram's div is assigned, so it is run
    // within runOutsideAngular
    if (divRef === null) return;
    this.diagram.div = divRef;
  });

}