7

I've noticed mousemove on certain element triggers change detection continuously. I've researched this issue and discovered they suggest to use runOutsideAngular method of NgZone.

So I tried like,

this.zone.runOutsideAngular(() => {
  this.element.addEventListener('mousemove', {});
});

which didn't work at all.

Did I misuse runOutsideAngular or is there any other workaround to prevent the endless change detection on mousemove event? Any insight would be appreciated!

DongBin Kim
  • 1,799
  • 5
  • 23
  • 43

2 Answers2

1

@EDIT For the comment question: the canvas element rendered by a third party library

Read this

For general purpose:

You need to use a renderer: Renderer2 listener.

Please read this Article

import { Component, OnInit, OnDestroy, NgZone, Renderer2, ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'app-mouse-tracker',
  templateUrl: './mouse-tracker.component.html',
  styleUrls: ['./mouse-tracker.component.css']
})
export class MouseTrackerComponent implements OnInit, OnDestroy {
  @ViewChild('area', { static: true }) area: ElementRef<HTMLDivElement>;
  private unlisten: Function;

  constructor(private ngZone: NgZone, private renderer: Renderer2) { }

  ngOnInit() {
    this.ngZone.runOutsideAngular(() => {
      this.unlisten = this.renderer.listen(
        this.area.nativeElement,
        'mousemove',
        () => this.drawLine()
      );
    });
  }

  ngOnDestroy() {
    this.unlisten();
  }

  drawLine() {
    console.log('Drawing a line which does not require bindings update...');
  }

  getLabel(): string {
    console.log('Label is being computed...');

    return 'exemplary label';
  }
}

and template:

<p>mouse-tracker works!</p>
<p>{{ getLabel() }}</p>

<div #area></div>
noririco
  • 765
  • 6
  • 15
  • Thanks for your answer. It works in a separate, pure element but the thing is that the one which triggers the change detection in my case is a canvas which is created by a library I'm using so I've tried your answer with: `this.renderer.listen(this.el.nativeElement // the container element which contains the canvas element, 'mousemove', () => {})` but it didn't work :( any idea? – DongBin Kim Oct 22 '19 at 08:40
  • `'mousemove', () => {}` is runOutsideAngular, in our example : this.drawLine() is the function that run oustise angular – noririco Oct 22 '19 at 08:44
  • I don't want to execute anything on `mousemove` event. The problem is that the change detection is triggered on every single mousemove on the container element which contains the canvas element rendered by a third party library so I was wondering if I could prevent to hear `mousemove` event or make Angular not detect the `mousemove` event by using runOutsideAngular method. – DongBin Kim Oct 22 '19 at 08:50
  • @DongBinKim `the canvas element rendered by a third party library ` , it must be a third party function, like: myCanvasObject.draw(), and then, this function will run outside. – noririco Oct 22 '19 at 08:57
  • Actually, nothing is supposed to happen upon mousemove event. It just keeps triggering the change detection on mousemove and that is the problem. – DongBin Kim Oct 22 '19 at 09:14
  • @DongBinKim have you managed to find a fix for this? – The.Wolfgang.Grimmer Aug 05 '23 at 01:25
0

I had this problem when the user was dragging dialog windows.

The solution was to inject ChangeDetectorRef and call detach() onMouseDown and reattach() onMouseUp

cursorrux
  • 1,382
  • 4
  • 9
  • 20
ptrwis
  • 1
  • 2