Como forçar a re-renderização de um componente no Angular 2? Para propósitos de depuração trabalhando com o Redux, eu gostaria de forçar um componente a renderizar novamente sua visualização, isso é possível?
Como forçar a re-renderização de um componente no Angular 2? Para propósitos de depuração trabalhando com o Redux, eu gostaria de forçar um componente a renderizar novamente sua visualização, isso é possível?
Respostas:
A renderização acontece após a detecção de alterações. Para forçar a detecção de alterações, para que os valores das propriedades dos componentes que foram alterados sejam propagados para o DOM (e o navegador renderize essas alterações na exibição), aqui estão algumas opções:
$rootScope.$digest()
- ou seja, verifique a árvore de componentes completa$rootScope.$apply(callback)
- ou seja, avalie a função de retorno de chamada dentro da zona Angular 2. Eu acho, mas não tenho certeza, que isso acaba verificando a árvore de componentes completa após a execução da função de retorno de chamada.$scope.$digest()
- ou seja, verifique apenas este componente e seus filhosVocê precisará importar e injetar ApplicationRef
, NgZone
ou ChangeDetectorRef
em seu componente.
Para o seu cenário específico, eu recomendaria a última opção se apenas um único componente tiver sido alterado.
this is the first time I am facing an update not working in ng2
. A estratégia de detecção de alterações é padrão, então eu sei que não estraguei a estratégia de detecção de alterações.
this
contexto apropriado no retorno de chamada POST.
pure:false
o tubo. Funciona, mas é muito caro (ineficiente) para o meu caso de uso.
tx, encontrei a solução que eu precisava:
constructor(private zone:NgZone) {
// enable to for time travel
this.appStore.subscribe((state) => {
this.zone.run(() => {
console.log('enabled time travel');
});
});
executar zone.run forçará o componente a renderizar novamente
Abordagem 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();
}
}
Eu forço a recarregar meu componente usando * ngIf.
Todos os componentes dentro do meu contêiner retornam aos ganchos do ciclo de vida completo.
No modelo:
<ng-container *ngIf="_reload">
components here
</ng-container>
Então no arquivo ts:
public _reload = true;
private reload() {
setTimeout(() => this._reload = false);
setTimeout(() => this._reload = true);
}
setTimeout()
. Agora o meu está trabalhando com uma solução simples e leve!
Outras respostas aqui fornecem soluções para acionar ciclos de detecção de alterações que atualizarão a exibição do componente (que não é a mesma que re-renderização completa).
Completa re-render, o que destruiria e reinicializar componente (chamando todos os ganchos de ciclo de vida e reconstruir vista) pode ser feito usando ng-template
, ng-container
e ViewContainerRef
na seguinte forma:
<div>
<ng-container #outlet >
</ng-container>
</div>
<ng-template #content>
<child></child>
</ng-template>
Em seguida, no componente com referência a ambos #outlet
e #content
podemos limpar o conteúdo dos pontos de venda e inserir outra instância do componente filho:
@ViewChild("outlet", {read: ViewContainerRef}) outletRef: ViewContainerRef;
@ViewChild("content", {read: TemplateRef}) contentRef: TemplateRef<any>;
private rerender() {
this.outletRef.clear();
this.outletRef.createEmbeddedView(this.contentRef);
}
Além disso, o conteúdo inicial deve ser inserido no AfterContentInit
gancho:
ngAfterContentInit() {
this.outletRef.createEmbeddedView(this.contentRef);
}
Solução de trabalho completa pode ser encontrada aqui https://stackblitz.com/edit/angular-component-rerender .
ChangeDetectorRef.detectChanges()
geralmente é a maneira mais focada de fazer isso. ApplicationRef.tick()
geralmente é uma abordagem excessiva da marreta.
Para usar ChangeDetectorRef.detectChanges()
, você precisará disso na parte superior do seu componente:
import { ChangeDetectorRef } from '@angular/core';
... então, geralmente você alias que quando você injeta em seu construtor como este:
constructor( private cdr: ChangeDetectorRef ) { ... }
Então, no local apropriado , você chama assim:
this.cdr.detectChanges();
Onde você liga ChangeDetectorRef.detectChanges()
pode ser altamente significativo. Você precisa entender completamente o ciclo de vida e exatamente como seu aplicativo está funcionando e processando seus componentes. Não há substituto aqui para fazer completamente sua lição de casa e garantir que você entenda o ciclo de vida angular de dentro para fora. Então, depois de entender isso, você pode usá-lo ChangeDetectorRef.detectChanges()
adequadamente (às vezes é muito fácil entender onde você deve usá-lo, outras vezes pode ser muito complexo).