0

I'm trying to create a Directive that accepts a string to pass to HostListener. Basically a Directive to stop event propagation for any event.

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

@Directive({
  selector: '[crmDisableEventPropagation]'
})
export class DisableClickPropagation {
  public myStr: string;

  @HostListener('click', ['$event'])
  public onClick(event: any): void {
    event.stopPropagation();
  }
}

Right now I have 'click' hardwired as the HostListener parameter. But I am wondering if there is a way (maybe using generics or something similar) to use this one Directive for any kind of event without having to create a different directive per event.

Francisco Aguilera
  • 3,099
  • 6
  • 31
  • 57

1 Answers1

2

You can't use event name as a generic parameter in @HostListener decorator because it should be know at compile time.

But you can handle events with another approach.

For example, you can try Renderer2.listen

import { Directive, Renderer2, Input } from '@angular/core';

@Directive({
  selector: '[crmDisableEventPropagation]'
})
export class DisableClickPropagation implements OnInit, OnDestroy {
  @Input('crmDisableEventPropagation') event: string;

  listener: () => void;

  constructor(private renderer: Renderer2, private host: ElementRef) {}

  ngOnInit(): void {
    this.listener = this.renderer.listen(
      this.host.nativeElement,
      this.event,
      e => e.stopPropagation()
    );
  }
  
  ngOnDestroy() {
    this.listener();
  }
}

Now use it as follows:

some.html

<div crmDisableEventPropagation="click">

Note that you can also use different approach like observable fromEvent

See also How can I listen for keypress event on the whole page?

Community
  • 1
  • 1
yurzui
  • 205,937
  • 32
  • 433
  • 399