I have a directive which needs to listen for any event provided declaratively by the engineer. Here's an example:
import { Directive, Input, ElementRef, HostListener, OnInit } from '@angular/core';
//--
import { Sandbox } from '../../../sandbox';
@Directive({ selector: '[addItem]' })
class AddNewItemDirective implements OnInit {
    @Input('addItem') data;
    @Input() on: string = 'click';
    constructor(private $: Sandbox, private element: ElementRef) { }
    ngOnInit() { console.log('@INIT', this); }
    @HostListener('click', ['$event']) handleEvent(e) {
        console.log('add-item', e);
    }
}
export { AddNewItemDirective };
Here's its usage:
<button class="btn btn-primary" [addItem]="{ name: 'Jeffrey' }" on="focus">Add New Item</button>
This works fine. However, my intuition told me I should be able to dynamically set the HostListener's arguments at render time based upon an input parameter:
@Directive({ selector: '[addItem]' })
class AddNewItemDirective implements OnInit {
    @Input('addItem') data;
    @Input() on: string = 'click';
    constructor(private $: Sandbox, private element: ElementRef) { }
    ngOnInit() { console.log('@INIT', this); }
    @HostListener(this.on, ['$event']) handleEvent(e) {
        console.log('add-item', e);
    }
}
Of course, this.on would not be overwritten with 'focus' until the time ngOnInit is invoked. To my surprise, this.on throws an error because undefined has no property 'on'. So when my directive class is instantiated, for whatever reason, this === undefined.
I found one similar question here, though, its looking to dynamically modify HostListener at runtime while I just need it modified at compile/render/instantiation time.
Can someone please shed light on how I can accomplish this?
Thx
HostListener is not dynamic, it can not be changed at runtime. You should use Renderer class, which provides listen method:
@Input()
public on:string;
private dispose:Function;
constructor(private renderer:Renderer, private elementRef:ElementRef){}
ngOnInit(){
    this.dispose = this.renderer.listen(this.elementRef.nativeElement, this.on, e => console.log(e));
}
ngOnDestroy(){
     this.dispose();
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With