javascript - navigationend - router events subscribe angular 4
Angular 2: ¿Cómo detectar cambios en una matriz?(propiedad @input) (6)
Es trabajo para mi:
@Component({
selector: ''my-component'',
templateUrl: ''./my-component.component.html'',
styleUrls: [''./my-component.component.scss'']
})
export class MyComponent implements DoCheck {
@Input() changeArray: MyClassArray[]= [];
private differ: IterableDiffers;
constructor(private differs: IterableDiffers) {
this.differ = differs;
}
ngDoCheck() {
const changes = this.differ.find(this.insertedTasks);
if (changes) {
this.myMethodAfterChange();
}
}
Tengo un componente principal que recupera una matriz de objetos utilizando una solicitud ajax.
Este componente tiene dos componentes secundarios: uno muestra los objetos en una estructura de árbol y el otro presenta su contenido en formato de tabla. El padre pasa la matriz a sus hijos a través de una propiedad @input y muestran el contenido correctamente. Todo como se esperaba.
El problema ocurre cuando cambia algún campo dentro de los objetos: los componentes secundarios no son notificados de esos cambios. Los cambios solo se activan si reasigna manualmente la matriz a su variable.
Estoy acostumbrado a trabajar con Knockout JS y necesito obtener un efecto similar al de observableArrays.
He leído algo sobre DoCheck pero no estoy seguro de cómo funciona.
Esto ya aparece respondido.
Sin embargo, para los futuros buscadores de problemas, quería agregar algo que faltaba cuando investigaba y depuraba un problema de detección de cambios que tenía.
Ahora, mi problema estaba un poco aislado, y es un error estúpido de mi parte, pero sin embargo relevante.
Cuando esté actualizando los valores en la
Array
u
Object
en referencia, asegúrese de estar en el alcance correcto.
Me puse en una trampa usando
setInterval(myService.function, 1000)
, donde
myService.function()
actualizaría los valores de una matriz pública que utilicé fuera del servicio.
En realidad, esto nunca actualizó la matriz, ya que el enlace estaba desactivado, y el uso correcto debería haber sido
setInterval(myService.function.bind(this), 1000)
.
Perdí el tiempo intentando cambiar los trucos de detección, cuando era un error tonto / simple.
Elimine el alcance como culpable antes de intentar soluciones de detección de cambios;
Podría ahorrarte algo de tiempo.
Lea el siguiente artículo, no se pierda los objetos mutables vs inmutables.
La cuestión clave es que muta los elementos de la matriz, mientras que la referencia de la matriz permanece igual. Y la detección de cambios Angular2 verifica solo la referencia de matriz para detectar cambios. Después de comprender el concepto de objetos inmutables, comprenderá por qué tiene un problema y cómo resolverlo.
Utilizo la tienda redux en uno de mis proyectos para evitar este tipo de problemas.
https://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html
Puedes usar IterableDiffers
Lo usa *ngFor
constructor(private _differs: IterableDiffers) {}
ngOnChanges(changes: SimpleChanges): void {
if (!this._differ && value) {
this._differ = this._differs.find(value).create(this.ngForTrackBy);
}
}
ngDoCheck(): void {
if (this._differ) {
const changes = this._differ.diff(this.ngForOf);
if (changes) this._applyChanges(changes);
}
}
Siempre puede crear una nueva referencia a la matriz fusionándola con una matriz vacía:
this.yourArray = [{...}, {...}, {...}];
this.yourArray[0].yourModifiedField = "whatever";
this.yourArray = [].concat(this.yourArray);
El código anterior cambiará la referencia de la matriz y activará el mecanismo OnChanges en los componentes secundarios.
OnChanges
Lifecycle Hook
se activará solo cuando cambie la instancia de la propiedad de entrada.
Si desea verificar si un elemento dentro de la matriz de entrada se ha agregado, movido o eliminado, puede usar
IterableDiffers
dentro del
DoCheck
Lifecycle Hook de la siguiente manera:
constructor(private _iterableDiffers: IterableDiffers) {
this.iterableDiffer = this._iterableDiffers.find([]).create(null);
}
ngDoCheck() {
let changes = this.iterableDiffer.diff(this.inputArray);
if (changes) {
console.log(''Changes detected!'');
}
}
Si necesita detectar cambios en los objetos dentro de una matriz, deberá iterar a través de todos los elementos y aplicar KeyValueDiffers para cada elemento. (Puede hacer esto en paralelo con la verificación anterior).
Visita esta publicación para obtener más información: Detecta cambios en objetos dentro de la matriz en Angular2