¿Cómo detectar cuando un valor @Input() cambia en Angular?
Tengo un componente principal ( CategoryComponent ), un componente secundario ( videoListComponent ) y un ApiService.
La mayor parte de esto funciona 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 lista de videos solo obtiene todos los videos. Me gustaría filtrar esto solo para videos en una categoría en particular. Lo logré pasando el ID de categoría al niño a través de @Input()
.
CategoríaComponente.html
<video-list *ngIf="category" [categoryId]="category.id"></video-list>
Esto funciona y cuando la categoría principal CategoryComponent cambia, el valor de CategoryId se pasa @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 habría hecho una $watch
variable. ¿Cuál es la mejor manera de manejar esto?
En realidad, hay dos formas de detectar y actuar cuando una entrada cambia en el componente secundario en angular2+:
- Puede utilizar 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, Ejemplo de demostración de SimpleChange
: mire este plunker
- Como alternativa, también puede utilizar un definidor 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: Mire aquí .
Ejemplo de demostración: mira este plunker .
¿QUÉ ENFOQUE DEBE UTILIZAR?
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 entrada en particular (y no le importan las otras entradas), entonces podría ser más sencillo usar un definidor de propiedades de entrada. Sin embargo, este enfoque no proporciona una forma integrada de comparar los valores anteriores y actuales de la entrada modificada (lo que puede hacer fácilmente con el método de ciclo de vida ngOnChanges).
EDITAR 2017-07-25: LA DETECCIÓN DE CAMBIO ANGULAR PUEDE AÚN NO DISPARARSE BAJO ALGUNAS CIRCUNSTANCIAS
Normalmente, la detección de cambios tanto para setter como para ngOnChanges se activará cada vez que el componente principal cambie los datos que pasa al secundario, siempre que los datos sean un tipo de datos primitivo JS (cadena, número, booleano) . Sin embargo, en los siguientes escenarios, no se activará y deberás realizar acciones adicionales para que funcione.
Si está utilizando un objeto o matriz anidado (en lugar de un tipo de datos primitivo JS) para pasar datos de padre a hijo, es posible que la detección de cambios (usando setter o ngchanges) no se active, como también se menciona en la respuesta del usuario: muetzerich. Para soluciones, mire aquí .
Si está mutando datos fuera del contexto angular (es decir, externamente), entonces angular no sabrá de los cambios. Es posible que deba usar ChangeDetectorRef o NgZone en su componente para que Angular sea consciente de los cambios externos y, por lo tanto, active la detección de cambios. Consulte esto .
Utilice el ngOnChanges()
método del ciclo de vida en su componente.
Se llama a ngOnChanges justo después de que se hayan verificado las propiedades vinculadas a datos y antes de verificar la vista y el contenido de los elementos secundarios si al menos uno de ellos ha cambiado.
Aquí están los documentos .
Recibía errores en la consola, así como en el compilador y el IDE al usar el SimpleChanges
tipo en la firma de la función. Para evitar errores, utilice la any
palabra clave en la firma.
ngOnChanges(changes: any) {
console.log(changes.myInput.currentValue);
}
EDITAR:
Como Jon señaló a continuación, puede utilizar la SimpleChanges
firma cuando utilice la notación entre corchetes en lugar de la notación con puntos.
ngOnChanges(changes: SimpleChanges) {
console.log(changes['myInput'].currentValue);
}