Ofer Herman
Ofer Herman

Reputation: 3068

using HostListener in a structural directive

I have a structural directive in which it's needed to listen to events on the host like it's done on an attribute directive.

There is no error in using @HostListener in the directive but no event is received.

Here is the directive code:

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

import { TemplateRef, ViewContainerRef } from '@angular/core';

@Directive({ selector: '[myUnless]' })
export class UnlessDirective {

constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef
    ) { }

@HostListener("click", ["$event"]) public onClick(event: any) {
        console.log("click", event);
}

@Input() set myUnless(condition: boolean) {
    if (!condition) {
    this.viewContainer.createEmbeddedView(this.templateRef);
    } else {
    this.viewContainer.clear();
    }
}
}

and the template:

<h1>Structural Directive with HostListener</h1>


<p *myUnless="condition">
condition is false and myUnless is true.
</p>

<p *myUnless="!condition">
condition is true and myUnless is false.
</p>

There's also a plunker example

The question is if it's possible to use @HostListener in structural directives?

Upvotes: 10

Views: 4312

Answers (1)

yurzui
yurzui

Reputation: 214175

@HostListener works but it's applied to comment html tag like:

<!--template bindings={
  "ng-reflect-my-unless": "true"
}-->

You can try the following workaround:

@Directive({ selector: '[myUnless]' })
export class UnlessDirective {

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef,
    private renderer: Renderer) { }

  onClick(event: any) {
    console.log("click", event);
  }

  @Input() set myUnless(condition: boolean) {
    if (!condition) {
      this.viewContainer.createEmbeddedView(this.templateRef);

      const el = this.templateRef.elementRef.nativeElement.nextElementSibling;
      this.renderer.listen(el, 'click', this.onClick);  
    } else {
      this.viewContainer.clear();
    }
  }
}

Plunker

Upvotes: 12

Related Questions