Angular 8, il est obligatoire de renseigner une propriété static sur le ViewChild et ContentChlid
https://stackoverflow.com/questions/56359504/how-should-i-use-the-new-static-option-for-viewchild-in-angular-8
Queries timing
The
ViewChild
and ContentChild
decorators now must have a new option called static
. Let me explain why with a very simple example using a ViewChild
:
*ngIf="true">
#dynamicDiv>dynamic
Let’s get that element in our component and log it in the lifecycle hooks
ngOnInit
and ngAfterViewInit
:@ViewChild('dynamicDiv') dynamicDiv: ElementRef<HTMLDivElement>;
ngOnInit() {
console.log('init dynamic', this.dynamicDiv); // undefined
}
ngAfterViewInit() {
console.log('after view init dynamic', this.dynamicDiv); // div
}
Makes sense as AfterViewInit is called when the template initialization is done.
But in fact, if the queried element is static (not wrapped in an
ngIf
or an ngFor
), then it is available in ngOnInit
also:
#staticDiv>static
gives:
@ViewChild('staticDiv') staticDiv: ElementRef<HTMLDivElement>;
ngOnInit() {
console.log('init static', this.staticDiv); // div
}
ngAfterViewInit() {
console.log('after view init static', this.staticDiv); // div
}
This was not documented, or recommended, but that’s how it currently works.
With Ivy though, the behavior changes to be more consistent:
ngOnInit() {
console.log('init static', this.staticDiv); // undefined (changed)
}
ngAfterViewInit() {
console.log('after view init static', this.staticDiv); // div
}
A new
static
flag has been introduced to not break existing applications, so if you want to keep the old behavior even when you’ll switch to Ivy, you can write:@ViewChild('static', { static: true }) static: ElementRef<HTMLDivElement>;
and the behavior will be the same as the current one (the element is also accessible in
ngOnInit
).
Note that if you add
static: true
on a dynamic element (wrapped in a condition or a loop), then it will not be accessible in ngOnInit
nor in ngAfterViewInit
!static: false
will be how Ivy behaves by default.
To not break existing applications and to ease the migration, the Angular team wrote a schematic that automatically analyzes your application, and adds the
static
flag. It even offers two strategies:- one based on your templates, which will make sure that your application works (so it tends to mark queries as static even when they aren’t). You are sure it works, but it exposes you to problems if you wrap your static element in a condition or a loop later.
- one based on your usage of the query, which is more error-prone (as it is harder for the schematic to figure it out), but will not mark the queries as static if they don’t need to be. So most queries will have
static: false
, which will be the default in Ivy.
The first strategy is used by default when you run
ng update
because it is the safest, but you can try the usage strategy by using NG_STATIC_QUERY_USAGE_STRATEGY=true ng update
.
You can check out the official guide for more information.
This is what the migration looks like (with a failure in one component):
------ Static Query Migration ------
With Angular version 8, developers need to
explicitly specify the timing of ViewChild and
ContentChild queries. Read more about this here:
https://v8.angular.io/guide/static-query-migration
Some queries could not be migrated automatically. Please go
those manually and apply the appropriate timing.
For more info on how to choose a flag, please see:
https://v8.angular.io/guide/static-query-migration
⮑ home/home.component.ts@43:3: undefined
Note that this only concerns
ViewChild
and ContentChild
, not ViewChildren
and ContentChildren
(which will work the same way in Ivy and View Engine).
Aucun commentaire:
Enregistrer un commentaire
to criticize, to improve