web-dev-qa-db-fra.com

Comment dois-je utiliser la nouvelle option statique pour @ViewChild dans Angular 8?

Comment dois-je configurer le nouvel enfant Angular 8 view?

@ViewChild('searchText', {read: ElementRef, static: false})
public searchTextInput: ElementRef;

contre

@ViewChild('searchText', {read: ElementRef, static: true})
public searchTextInput: ElementRef;

Ce qui est mieux? Quand dois-je utiliser static:true contre static:false?

185
Patrik Laszlo

Dans la plupart des cas, vous voudrez utiliser {static: false}. Le définir ainsi garantira des correspondances de requête qui dépendent de la résolution de liaison (comme les directives structurelles *ngIf, etc...) sera trouvé.

Exemple d'utilisation de static: false:

@Component({
  template: `
    <div *ngIf="showMe" #viewMe>Am I here?</div>
    <button (click)="showMe = !showMe"></button>
  ` 
})
export class ExampleComponent {
  @ViewChild('viewMe', { static: false })
  viewMe?: ElementRef<HTMLElement>; 

  showMe = false;
}

Le static: false va être le comportement de secours par défaut dans Angular 9. En savoir plus ici et ici

Le { static: true } L'option a été introduite pour prendre en charge la création de vues intégrées à la volée. Lorsque vous créez une vue dynamiquement et souhaitez accéder à TemplateRef, vous ne pourrez pas le faire dans ngAfterViewInit car cela provoquera une erreur ExpressionHasChangedAfterChecked. La définition de l'indicateur statique sur true créera votre vue dans ngOnInit.

Néanmoins:

Dans la plupart des autres cas, la meilleure pratique consiste à utiliser {static: false}.

Sachez cependant que le { static: false } l'option sera définie par défaut dans Angular 9. Ce qui signifie que la définition de l'indicateur statique n'est plus nécessaire, sauf si vous souhaitez utiliser le static: true option.

Vous pouvez utiliser le angular cli ng update commande pour mettre à jour automatiquement votre base de code actuelle.

Pour un guide de migration et encore plus d'informations à ce sujet, vous pouvez consulter ici et ici

Quelle est la différence entre les requêtes statiques et dynamiques?

L'option statique pour les requêtes @ViewChild () et @ContentChild () détermine quand les résultats de la requête deviennent disponibles.

Avec les requêtes statiques (static: true), la requête se résout une fois la vue créée, mais avant l'exécution de la détection des modifications. Le résultat, cependant, ne sera jamais mis à jour pour refléter les modifications apportées à votre vue, telles que les modifications apportées aux blocs ngIf et ngFor.

Avec les requêtes dynamiques (statique: false), la requête est résolue après ngAfterViewInit () ou ngAfterContentInit () pour @ViewChild () et @ContentChild () respectivement. Le résultat sera mis à jour pour les modifications apportées à votre vue, telles que les modifications apportées aux blocs ngIf et ngFor.

198
PierreDuc

Donc, en règle générale, vous pouvez opter pour les éléments suivants:

  • { static: true } doit être défini lorsque vous souhaitez accéder à ViewChild dans ngOnInit.

  • { static: false } n'est accessible que dans ngAfterViewInit. C'est aussi ce que vous voulez faire lorsque vous avez une directive structurelle (c'est-à-dire *ngIf) sur votre élément dans votre modèle.

69
dave0688

Depuis le angular docs

statique - s'il faut ou non résoudre les résultats de la requête avant l'exécution de la détection des modifications (c'est-à-dire renvoyer uniquement les résultats statiques). Si cette option n'est pas fournie, le compilateur reviendra à son comportement par défaut, qui consiste à utiliser les résultats de la requête pour déterminer le moment de la résolution de la requête. Si des résultats de requête se trouvent dans une vue imbriquée (par exemple * ngIf), la requête sera résolue après l'exécution de la détection des modifications. Sinon, il sera résolu avant l'exécution de la détection des modifications.

Il peut être préférable d'utiliser static:true si l'enfant ne dépend d'aucune condition. Si la visibilité de l'élément change, alors static:false peut donner de meilleurs résultats.

PS: Étant donné qu'il s'agit d'une nouvelle fonctionnalité, nous devrons peut-être exécuter des tests de performances.

Éditer

Comme mentionné par @Massimiliano Sartoretto, github commit peut vous donner plus d'informations.

17
Sachin Gupta

afficher l'enfant @angular 5+ token deux arguments ('local reference name', static: false | true)

@ViewChild('nameInput', { static: false }) nameInputRef: ElementRef;

pour savoir la différence entre vrai et faux vérifier cela

statique - s'il faut ou non résoudre les résultats de la requête avant l'exécution de la détection des modifications (c'est-à-dire renvoyer uniquement les résultats statiques). Si cette option n'est pas fournie, le compilateur reviendra à son comportement par défaut, qui consiste à utiliser les résultats de la requête pour déterminer le moment de la résolution de la requête. Si des résultats de requête se trouvent dans une vue imbriquée (par exemple * ngIf), la requête sera résolue après l'exécution de la détection des modifications. Sinon, il sera résolu avant l'exécution de la détection des modifications.

1
Samar Abdallah

Entré ici car un ViewChild était nul dans ngOnInit après la mise à niveau vers Angular 8.

Les requêtes statiques sont remplies avant ngOnInit, tandis que les requêtes dynamiques (statiques: false) sont remplies après. En d'autres termes, si un enfant de vue est désormais nul dans ngOnInit après avoir défini static: false, vous devez envisager de passer à static: true ou déplacer le code vers ngAfterViewInit.

Voir https://github.com/angular/angular/blob/master/packages/core/src/view/view.ts#L332-L336

Les autres réponses sont correctes et expliquent pourquoi c'est le cas: les requêtes dépendant des directives structurelles, par ex. une référence ViewChild à l'intérieur d'un ngIf, devrait s'exécuter après que le conditionnel de cette directive a été résolu, c'est-à-dire après la détection de changement. Cependant, on peut utiliser en toute sécurité static: true et ainsi résoudre les requêtes avant ngOnInit pour les références non imbriquées. À mon humble avis, ce cas particulier mérite d'être mentionné comme une exception nulle.C'est probablement la première façon de rencontrer cette particularité, comme ce fut le cas pour moi.

1
corolla

Dans ng8, vous pouvez définir manuellement quand accéder au composant enfant dans le composant parent. Lorsque vous définissez static sur true, cela signifie que le composant parent obtient uniquement la définition du composant dans le crochet onInit: Par exemple:

 // You got a childComponent which has a ngIf/for tag
ngOnInit(){
  console.log(this.childComponent);
}

ngAfterViewInit(){
  console.log(this.childComponent);
}

Si statique est faux, vous n'obtiendrez que la définition dans ngAfterViewInit (), dans ngOnInit (), vous ne serez pas défini.

0
Tethys Zhang