@ViewChild in *ngIf @ViewChild in *ngIf angular angular

@ViewChild in *ngIf


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();    }


Angular 8+

You should add { static: false } as a second option for @ViewChild. This causes the query results to be resolved after change detection runs, allowing your @ViewChild to be updated after the value changes.

Example:

export class AppComponent {    @ViewChild('contentPlaceholder', { static: false }) contentPlaceholder: ElementRef;    display = false;    constructor(private changeDetectorRef: ChangeDetectorRef) {    }    show() {        this.display = true;        // Required to access this.contentPlaceholder below,        // otherwise contentPlaceholder will be undefined        this.changeDetectorRef.detectChanges();        console.log(this.contentPlaceholder);    }}

Stackblitz example: https://stackblitz.com/edit/angular-d8ezsn