Comment forcer le re-rendu d'un composant dans Angular 2? À des fins de débogage en travaillant avec Redux, je voudrais forcer un composant à restituer sa vue, est-ce possible?
Comment forcer le re-rendu d'un composant dans Angular 2? À des fins de débogage en travaillant avec Redux, je voudrais forcer un composant à restituer sa vue, est-ce possible?
Réponses:
Le rendu se produit après la détection des modifications. Pour forcer la détection des changements, afin que les valeurs des propriétés des composants qui ont changé soient propagées vers le DOM (puis le navigateur rendra ces changements dans la vue), voici quelques options:
$rootScope.$digest()
- c'est-à-dire, vérifiez l'arbre complet des composants$rootScope.$apply(callback)
- ie, évalue la fonction de callback à l'intérieur de la zone Angular 2. Je pense, mais je ne suis pas sûr, que cela finit par vérifier l'arborescence complète des composants après l'exécution de la fonction de rappel.$scope.$digest()
- c'est- à -dire, ne vérifie que ce composant et ses enfantsVous devrez importer puis injecter ApplicationRef
, NgZone
ou ChangeDetectorRef
dans votre composant.
Pour votre scénario particulier, je recommanderais la dernière option si un seul composant a changé.
this is the first time I am facing an update not working in ng2
. La stratégie de détection de changement est par défaut donc je sais que je n'ai pas foiré avec la stratégie de détection de changement.
this
contexte approprié dans le rappel POST.
pure:false
dans le tuyau. Cela fonctionne mais c'est beaucoup trop cher (inefficace) pour mon cas d'utilisation.
tx, j'ai trouvé la solution de contournement dont j'avais besoin:
constructor(private zone:NgZone) {
// enable to for time travel
this.appStore.subscribe((state) => {
this.zone.run(() => {
console.log('enabled time travel');
});
});
l'exécution de zone.run forcera le composant à effectuer un nouveau rendu
Approche ChangeDetectorRef
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
export class MyComponent {
constructor(private cdr: ChangeDetectorRef) { }
selected(item: any) {
if (item == 'Department')
this.isDepartment = true;
else
this.isDepartment = false;
this.cdr.detectChanges();
}
}
Je force le rechargement de mon composant en utilisant * ngIf.
Tous les composants à l'intérieur de mon conteneur retournent aux hooks du cycle de vie complet.
Dans le modèle:
<ng-container *ngIf="_reload">
components here
</ng-container>
Puis dans le fichier ts:
public _reload = true;
private reload() {
setTimeout(() => this._reload = false);
setTimeout(() => this._reload = true);
}
setTimeout()
. Maintenant, le mien travaille avec une solution simple et légère!
D'autres réponses ici fournissent des solutions pour déclencher des cycles de détection de changement qui mettront à jour la vue du composant (qui n'est pas la même chose que le rendu complet).
La ré-rendu, ce qui détruirait et composants réinitialise (appelant tous les crochets du cycle de vie et vue la reconstruction) peut être fait en utilisant ng-template
, ng-container
et de ViewContainerRef
la manière suivante:
<div>
<ng-container #outlet >
</ng-container>
</div>
<ng-template #content>
<child></child>
</ng-template>
Ensuite, dans le composant faisant référence aux deux #outlet
et #content
nous pouvons effacer le contenu des points de vente et insérer une autre instance de composant enfant:
@ViewChild("outlet", {read: ViewContainerRef}) outletRef: ViewContainerRef;
@ViewChild("content", {read: TemplateRef}) contentRef: TemplateRef<any>;
private rerender() {
this.outletRef.clear();
this.outletRef.createEmbeddedView(this.contentRef);
}
De plus, le contenu initial doit être inséré au AfterContentInit
crochet:
ngAfterContentInit() {
this.outletRef.createEmbeddedView(this.contentRef);
}
La solution de travail complète peut être trouvée ici https://stackblitz.com/edit/angular-component-rerender .
ChangeDetectorRef.detectChanges()
est généralement la manière la plus ciblée d'y parvenir. ApplicationRef.tick()
est généralement trop une approche de masse.
Pour l'utiliser ChangeDetectorRef.detectChanges()
, vous en aurez besoin en haut de votre composant:
import { ChangeDetectorRef } from '@angular/core';
... alors, généralement vous alias que lorsque vous l'injectez dans votre constructeur comme ceci:
constructor( private cdr: ChangeDetectorRef ) { ... }
Ensuite, à l' endroit approprié , vous l'appelez comme ceci:
this.cdr.detectChanges();
L'endroit où vous appelez ChangeDetectorRef.detectChanges()
peut être très important. Vous devez comprendre complètement le cycle de vie et exactement comment votre application fonctionne et rend ses composants. Il n'y a pas de substitut ici pour faire complètement vos devoirs et vous assurer de comprendre le cycle de vie angulaire à fond. Ensuite, une fois que vous avez compris cela, vous pouvez l'utiliser de ChangeDetectorRef.detectChanges()
manière appropriée (parfois il est très facile de comprendre où vous devez l'utiliser, d'autres fois, cela peut être très complexe).