¿Cómo forzar la re-representación de un componente en Angular 2? Para fines de depuración que trabajen con Redux, me gustaría obligar a un componente a volver a representar su vista, ¿es eso posible?
¿Cómo forzar la re-representación de un componente en Angular 2? Para fines de depuración que trabajen con Redux, me gustaría obligar a un componente a volver a representar su vista, ¿es eso posible?
Respuestas:
El renderizado ocurre después de la detección de cambios. Para forzar la detección de cambios, de modo que los valores de las propiedades de los componentes que han cambiado se propaguen al DOM (y luego el navegador mostrará esos cambios en la vista), estas son algunas opciones:
$rootScope.$digest()
- es decir, verifique el árbol de componentes completo$rootScope.$apply(callback)
- es decir, evaluar la función de devolución de llamada dentro de la zona Angular 2. Creo, pero no estoy seguro, que esto termina comprobando el árbol de componentes completo después de ejecutar la función de devolución de llamada.$scope.$digest()
- es decir, verifique solo este componente y sus elementos secundariosUsted tendrá que importar y luego inyectar ApplicationRef
, NgZone
o ChangeDetectorRef
en su componente.
Para su escenario particular, recomendaría la última opción si solo un componente ha cambiado.
this is the first time I am facing an update not working in ng2
. La estrategia de detección de cambios es la predeterminada, así que sé que no me he equivocado con la estrategia de detección de cambios.
this
contexto adecuado en la devolución de llamada POST.
pure:false
la tubería. Funciona pero es demasiado caro (ineficiente) para mi caso de uso.
tx, encontré la solución que necesitaba:
constructor(private zone:NgZone) {
// enable to for time travel
this.appStore.subscribe((state) => {
this.zone.run(() => {
console.log('enabled time travel');
});
});
ejecutar zone.run forzará al componente a volver a renderizar
Enfoque 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();
}
}
Obligo a recargar mi componente usando * ngIf.
Todos los componentes dentro de mi contenedor vuelven a los ganchos de ciclo de vida completo.
En la plantilla:
<ng-container *ngIf="_reload">
components here
</ng-container>
Luego en el archivo ts:
public _reload = true;
private reload() {
setTimeout(() => this._reload = false);
setTimeout(() => this._reload = true);
}
setTimeout()
. ¡Ahora el mío está trabajando con una solución simple y ligera!
Otras respuestas aquí proporcionan soluciones para desencadenar ciclos de detección de cambios que actualizarán la vista del componente (que no es lo mismo que el renderizado completo).
Completa volver a hacer, lo que destruiría y reinicializar componente (llamando a todos los ganchos de ciclo de vida y la reconstrucción de la vista) se puede hacer mediante el uso ng-template
, ng-container
y ViewContainerRef
en la siguiente forma:
<div>
<ng-container #outlet >
</ng-container>
</div>
<ng-template #content>
<child></child>
</ng-template>
A continuación, en referencia a componente que tiene tanto #outlet
y #content
podemos borrar el contenido de puntos de venta e insertar otra instancia de componente secundario:
@ViewChild("outlet", {read: ViewContainerRef}) outletRef: ViewContainerRef;
@ViewChild("content", {read: TemplateRef}) contentRef: TemplateRef<any>;
private rerender() {
this.outletRef.clear();
this.outletRef.createEmbeddedView(this.contentRef);
}
Además, el contenido inicial debe insertarse en el AfterContentInit
gancho:
ngAfterContentInit() {
this.outletRef.createEmbeddedView(this.contentRef);
}
La solución de trabajo completa se puede encontrar aquí https://stackblitz.com/edit/angular-component-rerender .
ChangeDetectorRef.detectChanges()
suele ser la forma más enfocada de hacer esto. ApplicationRef.tick()
Por lo general, es demasiado un enfoque de mazo.
Para usarlo ChangeDetectorRef.detectChanges()
, necesitará esto en la parte superior de su componente:
import { ChangeDetectorRef } from '@angular/core';
... entonces, usualmente alias eso cuando lo inyectas en tu constructor así:
constructor( private cdr: ChangeDetectorRef ) { ... }
Luego, en el lugar apropiado , lo llamas así:
this.cdr.detectChanges();
Donde llamasChangeDetectorRef.detectChanges()
puede ser muy significativo. Usted necesita completamente comprender el ciclo de vida y exactamente cómo su aplicación está funcionando y la prestación de sus componentes. Aquí no hay sustituto para hacer su tarea por completo y asegurarse de comprender el ciclo de vida Angular al revés. Luego, una vez que comprenda eso, puede usarlo ChangeDetectorRef.detectChanges()
adecuadamente (a veces es muy fácil entender dónde debe usarlo, otras veces puede ser muy complejo).