16

Angular v8 has just been released. Although it's mostly backward compatible, there's some Breaking Changes.

According to Angular's Changelog one core change is (and I quote):

"In Angular version 8, it's required that all @ViewChild and @ContentChild queries have a 'static' flag specifying whether the query is 'static' or 'dynamic'."

It's also state that in most cases just setting { static: false } will do the trick.

@ViewChild('selectorName', { static: false }) varName: any;

My question is when should I set this attribute (static) to be true? and how will it effect my application???

Community
  • 1
  • 1
Gil Epshtain
  • 8,670
  • 7
  • 63
  • 89

3 Answers3

38

Use { static: true } when you want to access the ViewChild in ngOnInit.

Use { static: false } will be accessible only in ngAfterViewInit. This is also what you want to do for when you have a structural directive (*ngIf etc.) in your template.

In most cases { static: false } will work.

import { Component, OnInit, AfterViewInit, ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.scss']
})
export class ExampleComponent implements OnInit, AfterViewInit
{
  @ViewChild('elementA', { static: true }) elementStatic: ElementRef<HTMLElement>;
  @ViewChild('elementB', { static: false }) elementDynamic: ElementRef<HTMLElement>;
        
  public ngOnInit(): void
  {
    this.elementStatic.nativeElement; // Ok
    this.elementDynamic.nativeElement; // ERROR TypeError: Cannot read property 'nativeElement' of undefined 
  }
  
  public ngAfterViewInit(): void
  {
    this.elementStatic.nativeElement; // Ok
    this.elementDynamic.nativeElement; // Ok
  }
}
<div #elementA>A</div>
<div #elementB>B</div>

Update: Starting from Angular v9.x static has a default value of false.
Read more at: https://angular.io/api/core/ViewChild#viewchild

Gil Epshtain
  • 8,670
  • 7
  • 63
  • 89
  • I would like to correct that for the case of `@ContentChild` the non-static is available in `ngAfterContentInit` – Akxe Sep 03 '19 at 22:43
  • What's the downside of the old @ViewChild than the new @ViewChild? I feel the previous one is more helpful than in today's update – aj go Oct 07 '20 at 11:01
5

From the documentation:

How do I choose which static flag value to use: true or false?

In the official API docs, we have always recommended retrieving query results in ngAfterViewInit for view queries and ngAfterContentInit for content queries. This is because by the time those lifecycle hooks run, change detection has completed for the relevant nodes and we can guarantee that we have collected all the possible query results.

Most applications will want to use {static: false} for the same reason. This setting will ensure query matches that are dependent on binding resolution (e.g. results inside *ngIfs or *ngFors) will be found by the query.

There are rarer cases where {static: true} flag might be necessary (see answer here).

https://angular.io/guide/static-query-migration

Community
  • 1
  • 1
Sonu Kapoor
  • 1,567
  • 3
  • 16
  • 34
  • 3
    Thanks for this, but can you please write an answer, with **explanations**. And not just copy-n-paste a part of the documentation. – Gil Epshtain Jul 13 '19 at 14:49
0

When to use {static:true}

https://angular.io/guide/static-query-migration#should-i-use-static-true

This explains in very simple terms.