web-dev-qa-db-fra.com

Comment forcer le re-rendu d'un composant dans Angular 2?

Comment forcer le re-rendu d'un composant dans Angular 2? Pour le débogage avec Redux, je voudrais forcer un composant à restituer sa vue, est-ce possible?

151
born2net

Le rendu a lieu après la détection des modifications. Pour forcer la détection des modifications, de sorte que les valeurs de propriété de composant modifiées soient propagées au DOM (puis le navigateur rendra ces modifications dans la vue), voici quelques options:

  • ApplicationRef.tick () - semblable à Angular 1 $rootScope.$digest() - c'est-à-dire, consulter l'arborescence complète du composant
  • NgZone.run (callback) - similaire à $rootScope.$apply(callback) - c'est-à-dire, évaluez la fonction de rappel à l'intérieur de la zone Angular 2. Je pense, mais je ne suis pas sûr, que cela finira par vérifier l’arborescence complète des composants après avoir exécuté la fonction de rappel.
  • ChangeDetectorRef.detectChanges () - similaire à $scope.$digest() - c'est-à-dire, vérifiez uniquement ce composant et ses enfants

Vous 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 été modifié.

193
Mark Rajcok

tx, a 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');
        });
    });

exécuter zone.run forcera le composant à effectuer un nouveau rendu

45
born2net

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();
    }

}
17
Feng Zhang

D'autres réponses proposées ici proposent des solutions pour déclencher des cycles de détection de changement qui mettront à jour la vue du composant (ce qui n'est pas la même chose que le rendu complet).

Le re-rendu complet, qui détruirait et réinitialiserait le composant (appelant tous les crochets du cycle de vie et la vue de reconstruction) peut être effectué en utilisant ng-template, ng-container et ViewContainerRef de 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 à la fois à #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é sur AfterContentInit hook:

ngAfterContentInit() {
    this.outletRef.createEmbeddedView(this.contentRef);
}

La solution de travail complète peut être trouvée ici https://stackblitz.com/edit/angular-component-rerender .

5
Pavel Gurecki

Je force le rechargement de mon composant avec * ngIf.

Tous les composants de mon conteneur remontent à tous les crochets du cycle de vie.

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);
}
2
loonis

ChangeDetectorRef.detectChanges() est généralement le moyen le plus ciblé de le faire. ApplicationRef.tick() est généralement une approche trop brutale.

Pour utiliser ChangeDetectorRef.detectChanges(), vous aurez besoin de ceci en haut de votre composant:

import {  ChangeDetectorRef } from '@angular/core';

... alors, d'habitude vous alias que quand vous l'injectez dans votre constructeur comme ceci:

constructor( private cdr: ChangeDetectorRef ) { ... }

Ensuite, dans le endroit approprié , vous l'appelez comme ceci:

this.cdr.detectChanges();

vous appelez ChangeDetectorRef.detectChanges() peut être très significatif. Vous devez parfaitement comprendre le cycle de vie et le fonctionnement de votre application, ainsi que le rendu de ses composants. Ici, rien ne saurait remplacer vos devoirs et vos connaissances du cycle de vie Angular. Ensuite, une fois que vous aurez compris cela, vous pourrez utiliser ChangeDetectorRef.detectChanges() de manière appropriée (il est parfois très facile de comprendre où vous devez l’utiliser, d’autres fois, cela peut être très complexe).

0
Chris Halcrow