tablas reactivos formularios dinamicas angular angular2-changedetection

reactivos - tablas dinamicas angular 4



¿Cómo detectar cuándo un valor @Input() cambia en Angular? (10)

Tengo un componente principal ( CategoryComponent ), un componente secundario ( videoListComponent ) y un ApiService.

Tengo la mayor parte de esto funcionando bien, es decir, cada componente puede acceder a la API json y obtener sus datos relevantes a través de observables.

Actualmente, el componente de la lista de videos solo obtiene todos los videos, me gustaría filtrar esto solo a videos en una categoría particular, lo logré pasando el @Input() categoría al niño a través de @Input() .

CategoryComponent.html

<video-list *ngIf="category" [categoryId]="category.id"></video-list>

Esto funciona y cuando la categoría principal de CategoryComponent cambia, el valor de categoryId se transfiere a través de @Input() pero luego necesito detectar esto en VideoListComponent y volver a solicitar la matriz de videos a través de APIService (con el nuevo categoryId).

En AngularJS hubiera hecho un $watch en la variable. ¿Cuál es la mejor manera de manejar esto?


Aquí ngOnChanges se activará siempre cuando cambie la propiedad de entrada:

ngOnChanges(changes: SimpleChanges): void { console.log(changes.categoryId.currentValue) }



La apuesta más segura es ir con un servicio compartido en lugar de un parámetro @Input . Además, el parámetro @Input no detecta cambios en el tipo de objeto anidado complejo.

Un servicio de ejemplo simple es el siguiente:

Service.ts

import { Injectable } from ''@angular/core''; import { Subject } from ''rxjs/Subject''; @Injectable() export class SyncService { private thread_id = new Subject<number>(); thread_id$ = this.thread_id.asObservable(); set_thread_id(thread_id: number) { this.thread_id.next(thread_id); } }

Component.ts

export class ConsumerComponent implements OnInit { constructor( public sync: SyncService ) { this.sync.thread_id$.subscribe(thread_id => { **Process Value Updates Here** } } selectChat(thread_id: number) { <--- How to update values this.sync.set_thread_id(thread_id); } }

Puede usar una implementación similar en otros componentes y todos sus componentes compartirán los mismos valores compartidos.


Recibía errores en la consola, así como en el compilador e IDE al usar el tipo SimpleChanges en la firma de la función. Para evitar los errores, use la palabra clave any en la firma.

ngOnChanges(changes: any) { console.log(changes.myInput.currentValue); }

EDITAR:

Como Jon señaló a continuación, puede usar la firma SimpleChanges al usar la notación de corchetes en lugar de la notación de puntos.

ngOnChanges(changes: SimpleChanges) { console.log(changes[''myInput''].currentValue); }


Si no desea utilizar el método ngOnChange implement og onChange (), también puede suscribirse a los cambios de un elemento específico por el evento valueChanges , ETC.

myForm= new FormGroup({ first: new FormControl()

});

this.myForm.valueChanges.subscribe(formValue => { this.changeDetector.markForCheck(); });

el markForCheck () escrito debido al uso en esta declaración:

changeDetection: ChangeDetectionStrategy.OnPush


Solo quiero agregar que hay otro DoCheck Lifecycle llamado DoCheck que es útil si el valor de @Input no es un valor primitivo.

Tengo una matriz como Input por lo que esto no OnChanges evento OnChanges cuando cambia el contenido (porque la comprobación de que Angular lo hace es ''simple'' y no profunda, por lo que la matriz sigue siendo una matriz, a pesar de que el contenido de la matriz ha cambiado )

Luego implemento un código de verificación personalizado para decidir si quiero actualizar mi vista con la matriz modificada.


También puede tener un observable que desencadena los cambios en el componente principal (CategoryComponent) y hacer lo que desea hacer en la suscripción en el componente secundario. (videoListComponent)

service.ts public categoryChange$ : ReplaySubject<any> = new ReplaySubject(1); ----------------- CategoryComponent.ts public onCategoryChange(): void { service.categoryChange$.next(); } ----------------- videoListComponent.ts public ngOnInit(): void { service.categoryChange$.subscribe(() => { // do your logic }); }


Use el método de ciclo de vida ngOnChanges() en su componente.

ngOnChanges se llama justo después de que se hayan verificado las propiedades enlazadas a datos y antes de que se verifiquen los elementos secundarios de vista y contenido si al menos uno de ellos ha cambiado.

Aquí están los Docs .


En realidad, hay dos formas de detectar y actuar cuando una entrada cambia en el componente secundario en angular2 +:

  1. Puede usar el método de ciclo de vida ngOnChanges () como también se menciona en respuestas anteriores:

@Input() categoryId: string; ngOnChanges(changes: SimpleChanges) { this.doSomething(changes.categoryId.currentValue); // You can also use categoryId.previousValue and // categoryId.firstChange for comparing old and new values }

Enlaces de documentación: ngOnChanges, SimpleChanges, SimpleChange
Ejemplo de demostración: mira este plunker

  1. Alternativamente, también puede usar un configurador de propiedades de entrada de la siguiente manera:

private _categoryId: string; @Input() set categoryId(value: string) { this._categoryId = value; this.doSomething(this._categoryId); } get categoryId(): string { return this._categoryId; }

Enlace de documentación: mira here .

Ejemplo de demostración: Mira este plunker .

¿QUÉ ENFOQUE DEBE USAR?

Si su componente tiene varias entradas, entonces, si usa ngOnChanges (), obtendrá todos los cambios para todas las entradas a la vez dentro de ngOnChanges (). Con este enfoque, también puede comparar los valores actuales y anteriores de la entrada que ha cambiado y tomar las medidas correspondientes.

Sin embargo, si desea hacer algo cuando solo cambia una sola entrada en particular (y no le importan las otras entradas), entonces podría ser más simple usar un configurador de propiedades de entrada. Sin embargo, este enfoque no proporciona una forma integrada de comparar los valores anteriores y actuales de la entrada modificada (que puede hacer fácilmente con el método del ciclo de vida ngOnChanges).

EDITAR 2017-07-25: LA DETECCIÓN DE CAMBIO ANGULAR PUEDE TODAVÍA NO FUERA DE FUEGO BAJO ALGUNAS CIRCUNSTANCIAS

Normalmente, la detección de cambios tanto para setter como para ngOnChanges se activará siempre que el componente padre cambie los datos que pasa al hijo, siempre que los datos sean un tipo de datos primitivo JS (cadena, número, booleano) . Sin embargo, en los siguientes escenarios, no se disparará y tendrá que tomar medidas adicionales para que funcione.

  1. Si está utilizando un objeto anidado o matriz (en lugar de un tipo de datos primitivo JS) para pasar datos de padre a hijo, la detección de cambios (usando setter o ngchanges) podría no activarse, como también se menciona en la respuesta del usuario: muetzerich. Para soluciones mira here .

  2. Si está mutando datos fuera del contexto angular (es decir, externamente), entonces angular no sabrá los cambios. Es posible que tenga que usar ChangeDetectorRef o NgZone en su componente para hacer que Angular tenga conocimiento de los cambios externos y, por lo tanto, desencadenar la detección de cambios. Consulte this .


@Input() public set categoryId(categoryId: number) { console.log(categoryId) }

Intenta usar este método. Espero que esto ayude