In my parent ponent, I have a btn and a settings menu directive. What I am trying to do is pass the elementref #navBtn as an input into settings-menu.
<div #navBtn (click)="toggleNav()" class="header__button header__button--left" id="header_button--left">
<img class="align-absolute" src="assets/imgs/icon_sandwich.svg">
</div>
<settings-menu [btn]="navBtn" [navOpened]="navOpened" (navClosed)="navOpened.next(false)"></settings-menu>
...
@ViewChild('navBtn') navBtn: ElementRef;
I need this elementref so I can check to see if an event target includes/excludes this element in a HostListener on offclick.
private _btn: ElementRef;
@Input('navOpened') navOpened: BehaviorSubject<boolean>;
@Input('btn')
set btn(val: ElementRef) {
this._btn = val;
}
get btn() {
return this._btn;
}
@HostListener('document:click', ['$event']) offClick(e: Event) {
e.stopPropagation();
console.log('el', this.el.nativeElement, 'btn', this.btn.nativeElement, 'target', e.target);
if (!this.el.nativeElement.contains(e.target) || this.btn.nativeElement.contains(e.target)) this.closeNav();
}
But this.btn returns the btn html and not an elementRef it seems, because nativeElement on this.btn is always undefined, even in the ngAfterViewInit lifecycle hook.
In my parent ponent, I have a btn and a settings menu directive. What I am trying to do is pass the elementref #navBtn as an input into settings-menu.
<div #navBtn (click)="toggleNav()" class="header__button header__button--left" id="header_button--left">
<img class="align-absolute" src="assets/imgs/icon_sandwich.svg">
</div>
<settings-menu [btn]="navBtn" [navOpened]="navOpened" (navClosed)="navOpened.next(false)"></settings-menu>
...
@ViewChild('navBtn') navBtn: ElementRef;
I need this elementref so I can check to see if an event target includes/excludes this element in a HostListener on offclick.
private _btn: ElementRef;
@Input('navOpened') navOpened: BehaviorSubject<boolean>;
@Input('btn')
set btn(val: ElementRef) {
this._btn = val;
}
get btn() {
return this._btn;
}
@HostListener('document:click', ['$event']) offClick(e: Event) {
e.stopPropagation();
console.log('el', this.el.nativeElement, 'btn', this.btn.nativeElement, 'target', e.target);
if (!this.el.nativeElement.contains(e.target) || this.btn.nativeElement.contains(e.target)) this.closeNav();
}
But this.btn returns the btn html and not an elementRef it seems, because nativeElement on this.btn is always undefined, even in the ngAfterViewInit lifecycle hook.
Share Improve this question asked Dec 20, 2017 at 14:50 YeysidesYeysides 1,2921 gold badge19 silver badges27 bronze badges1 Answer
Reset to default 5As mentioned in the Angular documentation about template reference variables:
<input #phone placeholder="phone number">
<!-- phone refers to the input element; pass its `value` to an event handler -->
<button (click)="callPhone(phone.value)">Call</button>
In most cases, Angular sets the reference variable's value to the element on which it was declared. In the previous example, phone refers to the phone number box. The phone button click handler passes the input value to the ponent's callPhone method.
In your code, if you pass navBtn
as an input value to settings-menu
:
<settings-menu [btn]="navBtn" ...>
btn
will be set to the DOM element referred to by #navBtn
. You could define the btn
variable as an HTMLElement in the settings-menu
ponent:
@Input("btn") btn: HTMLElement;
On the other hand, if you retrieve the element with @ViewChild("navBtn")
in its own ponent, then you get an ElementRef
, with a nativeElement
property that points to the DOM element.