@ViewChild in *ngIf

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

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

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