Angular 2 @ViewChild in *ngIf



What is the most elegant way to get @ViewChild after corresponding element in template was shown? Below is an example. Also Plunker available.


<div id="layout" *ngIf="display">
    <div #contentPlaceholder></div>


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.

ANSWER (Plunker)

This could work but I don't know if it's convenient for your case:

@ViewChildren('contentPlaceholder', {read: ViewContainerRef}) viewContainerRefs: QueryList;

ngAfterViewInit() {
 this.viewContainerRefs.changes.subscribe(item => {
   if(this.viewContainerRefs.toArray().length) {
     // shown

The accepted answer using a QueryList did not work for me. However what did work was using a setter for the ViewChild:

 private contentPlaceholder: ViewContainerRef;

 @ViewChild('contentPlaceholder') set content(content: ViewContainerRef) {
    this.contentPlaceholder = content;

The setter is called once *ngIf becomes true.

This video can help you solving your question :)
By: admin