# Static query migration guide **Important note for library authors: This migration is especially crucial for library authors to facilitate their users upgrading to version 9 when it becomes available.** In version 9, the default setting for `@ViewChild` and `@ContentChild` queries is changing in order to fix buggy and surprising behavior in queries (read more about that [here](#what-does-this-flag-mean)). In preparation for this change, in version 8, we are migrating all applications and libraries to explicitly specify the resolution strategy for `@ViewChild` and `@ContentChild` queries. Specifically, this migration adds an explicit "static" flag that dictates when that query's results should be assigned. Adding this flag will ensure your code works the same way when upgrading to version 9. Before: ``` // query results sometimes available in `ngOnInit`, sometimes in `ngAfterViewInit` (based on template) @ViewChild('foo') foo: ElementRef; ``` After: ``` // query results available in ngOnInit @ViewChild('foo', {static: true}) foo: ElementRef; OR // query results available in ngAfterViewInit @ViewChild('foo', {static: false}) foo: ElementRef; ``` Starting with version 9, the `static` flag will default to false. At that time, any `{static: false}` flags can be safely removed, and we will have a schematic that will update your code for you. Note: this flag only applies to `@ViewChild` and `@ContentChild` queries specifically, as `@ViewChildren` and `@ContentChildren` queries do not have a concept of static and dynamic (they are always resolved as if they are "dynamic"). ## FAQ {@a what-to-do-with-todo} ### What should I do if I see a `/* TODO: add static flag */` comment printed by the schematic? If you see this comment, it means that the schematic couldn't statically figure out the correct flag. In this case, you'll have to add the correct flag based on your application's behavior. For more information on how to choose, see the [next question](#how-do-i-choose). {@a how-do-i-choose} ### 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](https://angular.io/api/core/ViewChild#description) and [`ngAfterContentInit` for content queries](https://angular.io/api/core/ContentChild#description). 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 `*ngIf`s or `*ngFor`s) will be found by the query. There are rarer cases where `{static: true}` flag might be necessary (see [answer here](#should-i-use-static-true)). {@a should-i-use-static-true} ### Is there a case where I should use `{static: true}`? This option was introduced to support creating embedded views on the fly. If you need access to a `TemplateRef` in a query to create a view dynamically, you won't be able to do so in `ngAfterViewInit`. Change detection has already run on that view, so creating a new view with the template will cause an `ExpressionHasChangedAfterChecked` error to be thrown. In this case, you will want to set the `static` flag to `true` and create your view in `ngOnInit`. In most other cases, the best practice is to use `{static: false}`. However, to facilitate the migration to version 8, you may also want to set the `static` flag to `true` if your component code already depends on the query results being available some time **before** `ngAfterViewInit` (for view queries) or `ngAfterContentInit` (for content queries). For example, if your component relies on the query results being populated in the `ngOnInit` hook or in `@Input` setters, you will need to either set the flag to `true` or re-work your component to adjust to later timing. Note: Selecting the static option means that query results nested in `*ngIf` or `*ngFor` will not be found by the query. These results are only retrievable after change detection runs. {@a what-does-this-flag-mean} ### What does this flag mean and why is it necessary? The default behavior for queries has historically been undocumented and confusing, and has also commonly led to issues that are difficult to debug. In version 9, we would like to make query behavior more consistent and simple to understand. To explain why, first it's important to understand how queries have worked up until now. Without the `static` flag, the compiler decided when each query would be resolved on a case-by-case basis. All `@ViewChild`/`@ContentChild` queries were categorized into one of two buckets at compile time: "static" or "dynamic". This classification determined when query results would become available to users. - **Static queries** were queries where the result could be determined statically because the result didn't depend on runtime values like bindings. Results from queries classified as static were available before change detection ran for that view (accessible in `ngOnInit`). - **Dynamic queries** were queries where the result could NOT be determined statically because the result depended on runtime values (aka bindings). Results from queries classified as dynamic were not available until after change detection ran for that view (accessible in `ngAfterContentInit` for content queries or `ngAfterViewInit` for view queries). For example, let's say we have a component, `Comp`. Inside it, we have this query: ``` @ViewChild(Foo) foo: Foo; ``` and this template: ```
``` This `Foo` query would be categorized as static because at compile-time it's known that the `Foo` instance on the `