Come forzare il rendering di un componente in Angular 2? Ai fini del debug, lavorando con Redux, vorrei forzare un componente per renderizzare nuovamente la visualizzazione, è possibile?
Come forzare il rendering di un componente in Angular 2? Ai fini del debug, lavorando con Redux, vorrei forzare un componente per renderizzare nuovamente la visualizzazione, è possibile?
Risposte:
Il rendering avviene dopo il rilevamento delle modifiche. Per forzare il rilevamento delle modifiche, in modo che i valori delle proprietà dei componenti che sono stati modificati vengano propagati al DOM (e quindi il browser renderà tali modifiche nella vista), ecco alcune opzioni:
$rootScope.$digest()
- ovvero, controlla l'albero dei componenti completo$rootScope.$apply(callback)
- cioè, valuta la funzione di callback all'interno della zona Angular 2. Penso, ma non sono sicuro, che questo finisca per controllare l'albero dei componenti completo dopo aver eseguito la funzione di callback.$scope.$digest()
- cioè, controlla solo questo componente e i suoi figliSarà necessario importare e poi iniettare ApplicationRef
, NgZone
o ChangeDetectorRef
nel componente.
Per il tuo particolare scenario, consiglierei l'ultima opzione se è cambiato solo un singolo componente.
this is the first time I am facing an update not working in ng2
. La strategia di rilevamento delle modifiche è predefinita, quindi so di non aver sbagliato con la strategia di rilevamento delle modifiche.
this
contesto corretto nel callback POST.
pure:false
la pipe. Funziona ma è troppo costoso (inefficiente) per il mio caso d'uso.
tx, ho trovato la soluzione alternativa di cui avevo bisogno:
constructor(private zone:NgZone) {
// enable to for time travel
this.appStore.subscribe((state) => {
this.zone.run(() => {
console.log('enabled time travel');
});
});
l'esecuzione di zone.run forza il rendering del componente
Approccio 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();
}
}
Forzo a ricaricare il mio componente usando * ngIf.
Tutti i componenti all'interno del mio contenitore risalgono ai ganci del ciclo di vita completo.
Nel modello:
<ng-container *ngIf="_reload">
components here
</ng-container>
Quindi nel file ts:
public _reload = true;
private reload() {
setTimeout(() => this._reload = false);
setTimeout(() => this._reload = true);
}
setTimeout()
. Ora il mio sta lavorando con una soluzione semplice e leggera!
Altre risposte qui forniscono soluzioni per l'attivazione di cicli di rilevamento delle modifiche che aggiorneranno la vista del componente (che non è la stessa del nuovo rendering completo).
Completa ri-renderizzare, che avrebbe distrutto e reinizializzare componente (chiamando tutti i ganci del ciclo di vita e la ricostruzione di vista) può essere fatto utilizzando ng-template
, ng-container
e ViewContainerRef
in questo modo:
<div>
<ng-container #outlet >
</ng-container>
</div>
<ng-template #content>
<child></child>
</ng-template>
Quindi nel componente con riferimento a entrambi #outlet
e #content
possiamo cancellare il contenuto dei punti vendita e inserire un'altra istanza del componente figlio:
@ViewChild("outlet", {read: ViewContainerRef}) outletRef: ViewContainerRef;
@ViewChild("content", {read: TemplateRef}) contentRef: TemplateRef<any>;
private rerender() {
this.outletRef.clear();
this.outletRef.createEmbeddedView(this.contentRef);
}
Inoltre, il contenuto iniziale deve essere inserito al AfterContentInit
gancio:
ngAfterContentInit() {
this.outletRef.createEmbeddedView(this.contentRef);
}
La soluzione di lavoro completa è disponibile qui https://stackblitz.com/edit/angular-component-rerender .
ChangeDetectorRef.detectChanges()
di solito è il modo più mirato per farlo. ApplicationRef.tick()
di solito è troppo un approccio con la mazza.
Per utilizzarlo ChangeDetectorRef.detectChanges()
, ti servirà nella parte superiore del componente:
import { ChangeDetectorRef } from '@angular/core';
... quindi, di solito alias che quando lo iniettate nel vostro costruttore in questo modo:
constructor( private cdr: ChangeDetectorRef ) { ... }
Quindi, nel posto appropriato , lo chiami in questo modo:
this.cdr.detectChanges();
Il luogo in cui chiami ChangeDetectorRef.detectChanges()
può essere molto significativo. È necessario comprendere completamente il ciclo di vita ed esattamente come funziona l'applicazione e renderizzarne i componenti. Non c'è sostituto qui per fare completamente i compiti e assicurarsi di aver compreso il ciclo di vita angolare. Quindi, una volta capito, puoi usarlo in modo ChangeDetectorRef.detectChanges()
appropriato (a volte è molto facile capire dove dovresti usarlo, altre volte può essere molto complesso).