What is the most elegant way to get @ViewChild
after corresponding element in template was shown?
Below is an example. Also Plunker available.
Component.template.html:
<div id="layout" *ngIf="display"> <div #contentPlaceholder></div> </div>
Component.component.ts:
export class AppComponent { display = false; @ViewChild('contentPlaceholder', { read: ViewContainerRef }) viewContainerRef; show() { this.display = true; console.log(this.viewContainerRef); // undefined setTimeout(() => { console.log(this.viewContainerRef); // OK }, 1); } }
I have a component with its contents hidden by default. When someone calls show()
method it becomes visible. However, before Angular 2 change detection completes, I can not reference to viewContainerRef
. I usually wrap all required actions into setTimeout(()=>{},1)
as shown above. Is there a more correct way?
I know there is an option with ngAfterViewChecked
, but it causes too much useless calls.
Use a setter for the ViewChild:
private contentPlaceholder: ElementRef; @ViewChild('contentPlaceholder') set content(content: ElementRef) { if(content) { // initially setter gets called with undefined this.contentPlaceholder = content; } }
The setter is called with an element reference once *ngIf
becomes true
.
Note, for Angular 8 you have to make sure to set { static: false }
, which is a default setting in other Angular versions:
@ViewChild('contentPlaceholder', { static: false })
Note: if contentPlaceholder is a component you can change ElementRef to your component Class:
private contentPlaceholder: MyCustomComponent; @ViewChild('contentPlaceholder') set content(content: MyCustomComponent) { if(content) { // initially setter gets called with undefined this.contentPlaceholder = content; } }
An alternative to overcome this is running the change detector manually.
You first inject the ChangeDetectorRef
:
constructor(private changeDetector : ChangeDetectorRef) {}
Then you call it after updating the variable that controls the *ngIf
show() { this.display = true; this.changeDetector.detectChanges(); }
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