3

Here is by Component which has a ViewChild referring to #h1 in the html:

import { Component, ElementRef, ViewChild } from '@angular/core';
@Component({
  selector: 'app-root',
  template: `
  <h1 #h1 *ngIf="showh1">
    Welcome to {{title}}!
  </h1>
  `,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
  public showh1: boolean = false;
  @ViewChild('h1') h1: ElementRef;
  ngOnInit() {
    setTimeout(() => { //http.get in actual scenario
      this.showh1 = true;
      console.log('h1:' + this.h1);   //h1:undefined
      setTimeout(() => {
        console.log('h2:' + this.h1); //h2:[object Object]
      }, 1);
    }, 1000);
  }
}

Why this.h1 is undefined at console.log('h1:' + this.h1); ?

Update 2020 Nov You wouldn't be in this situation if you are using latest Angularv9 which has static option on @ViewChild.

Anand Rockzz
  • 6,072
  • 5
  • 64
  • 71
  • You could run `applicationRef.tick()` after setting `showh1` to make it work (see [this answer](https://stackoverflow.com/a/47801027/1009922)). – ConnorsFan Dec 17 '17 at 21:13

1 Answers1

2

Because, since the condition passed to ngIf hasn't been reevaluated by the change detection at that point, the element is not in the view yet.

You need to understand that change detection, and dom updates, aren't done after each and every instruction of your code. Even if that was possible, it would make the performance horrible.

The loop is basically

  1. detect an event (like a timeout, or an asynchronous http response, or some dom event like a click)
  2. execute the code handling this event
  3. detect the changes in the state of the components, and in the expressions used in the template (like showh1)
  4. update the DOM
  5. go to 1
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255