Search code examples
angularangular-changedetection

Prevent MouseEvent on Angular directive from triggering change detection


I am working on an Angular project where a directive needs to react to mouseenter and mouseleave events. it needs to update the CSS of the host element where it is used.

Consider the contrived example below:

import { Directive, ElementRef, HostListener } from '@angular/core';

@Directive({
  selector: '[appMouseEvents]',
})
export class MouseEventsDirective {
  constructor(private element: ElementRef) {

  }
  @HostListener('mouseEnter', ['$event'])
  onMouseEnter() {
    console.log('mouseenter');
  }

  @HostListener('mouseleave',['$event'])
  onMouseLeave() {
    console.log('mouseleave');
  }

}

app.component.html

<hello name="{{ name }}"></hello>
<p appMouseEvents>
  Hover Mouse over me
</p>

When I profile the application in Angular Dev tools, I see that these event cause Angular to trigger change detection which is not needed as only the CSS of host element is affected. enter image description here

Is there a way to react to mouse event in the directive and not trigger change detection?

Here's a demo application: https://stackblitz.com/edit/angular-ivy-r6ln5w?file=src%2Fapp%2Fapp.component.ts


Solution

  • Yes, event fired on DOM would be monkey patched by zone.js and it triggers a change detection.

    I would suggest you to go here using native browser feature. Like use :hover pseudo css class on host element.

    :host:hover {
        // CSS rules
    }
    

    Alternative way to fix it would be using this.zone.runOutsideAngular as other suggested answer.