Aprende a comunicar entre los componentes, enviando propiedades desde el componente padre al hijo. Para ello usaremos el decorador @Input de Angular, que define que ciertas propiedades del componente puedan asignarse desde el template padre.
En artículos anteriores del Manual de Angular, al abordar la introducción al framework, hemos mencionado en varias ocasiones una de sus características fundamentales: la arquitectura de componentes.
Hemos dicho que una aplicación en Angular la forma un árbol de componentes, capaces de colaborar entre sí para resolver las necesidades del negocio. Pero lo cierto es que, hasta el momento nuestros componentes han funcionado de manera bastante autónoma, sin la posibilidad de interaccionar los unos con los otros.
En este artículo vamos a comenzar con la revisión de los procesos de comunicación habituales entre los componentes de aplicaciones, analizando especialmente el uso de las propiedades de entrada decoradas con @Input().
Envío de datos entre componentes
Es verdad que en pasados artículos hemos visto como un servicio es capaz de facilitar que los componentes compartan datos, pero no es la única manera que podemos conseguir ese objetivo.
Además de los servicios como comunicadores de datos, existen diferentes escenarios mediante los cuales los componentes pueden compartir información. Atendiendo a la estructura de árbol de componentes en la aplicación, esa comunicación puede surgir de los padres a los hijos y de los hijos hacia los padres.
Paso de datos de padres a hijos
El paso de información de padres a hijos se realiza por medio de propiedades del componente. La información se bindea desde el template, usando los atributos de la etiqueta del componente.
Para ello, las propiedades del componente se deben decorar con @Input, de modo que Angular sea capaz de saber que éstas son capaces de inicializarse, o modificarse, desde fuera. Este es el escenario que vamos a abordar en este artículo.
Paso de datos de los hijos a los padres
También puede surgir la necesidad de que los hijos comuniquen a los padres cambios en la información que ellos manejan. En estos casos Angular utiliza eventos. Es decir, cuando el hijo tiene un dato y quiere hacerlo llegar al padre, genera un evento que puede ser capturado en el padre para realizar aquellas acciones que sean necesarias.
Para definir los eventos que van de los hijos a los padres, Angular usa el decorador @Output, que veremos con detalle en el siguiente artículo.
Paso de datos desde componentes padre a componentes hijo
Ahora vamos a ver cómo se realiza el envío de datos del padre al hijo, comenzando por la definición del dato en el template.
Vamos a suponer que tenemos un componente que se llama VisualizarClienteComponent. Este componente muestra la ficha de un cliente, con sus datos principales (nombre, CIF...). Para funcionar, este componente debe recibir del padre los datos del cliente que debe mostrar.
Por otra parte, tenemos otro componente que usa a VisualizarClienteComponent, que le tiene que pasar los datos que debe mostrar. Al usar el componente, tiene que pasar los datos por medio del template, usando el binding de propiedades.
El uso del componente sería como este:
<dw-visualizar-cliente
[nombre]="cliente.nombre"
[cif]="cliente.cif"
[direccion]="cliente.direccion"
></dw-visualizar-cliente>
Como puedes ver, las propiedades se pasan por medio de binding, usando la sintaxis de los corchetes.
A la vista de este código se entiende que el componente padre tendrá un objeto cliente. El componente hijo tendrá tres propiedades, "nombre", "cif" y "direccion". A la propiedad nombre le pasaremos el valor de "cliente.nombre", a la propiedad "cif" le pasaremos el valor de "cliente.cif", etc.
Declaración de propiedades de entrada con @Input
A continuación vamos a ver cómo definir en el componente hijo las propiedades que son capaces de cargar datos desde el padre. Para ello usaremos el decorador @Input.
Importar el decorador @Input
Como un primer paso en el componente hijo necesitamos hacer el import del decorador Input, que está en "@angular/core".
import { Component, OnInit, Input } from '@angular/core';
Declarar las propiedades con su decorador @Input
También en el código TypeScript del componente hijo, tenemos que declarar las propiedades en la clase, igual que veníamos haciendo, solo que agregaremos el decorador @Input para indicar que esta propiedad se puede manipular desde el padre.
De momento vamos a dejar el decorador vacío, que será suficiente en la mayoría de los casos, aunque podríamos indicar algunas cuestiones como el nombre con el que conocerá la propiedad desde fuera.
@Input()
nombre: string;
Si se desea, es posible aplicar un valor predeterminado a la propiedad, asignando un valor cualquiera. En ese caso, si no se entrega ese valor al usar el componente, se asumirá el definido de manera predeterminada.
@Input()
nombre = 'DesarrolloWeb.com';
Código completo del componente
Aparte de los @Input, el código del componente no tiene nada que no se conozca hasta el momento. No obstante dejamos el código completo a continuación.
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'dw-visualizar-cliente',
templateUrl: './visualizar-cliente.component.html',
styleUrls: ['./visualizar-cliente.component.css']
})
export class VisualizarClienteComponent implements OnInit {
@Input()
nombre = 'DesarrolloWeb.com';
@Input()
cif: string;
@Input()
direccion: string;
constructor() { }
ngOnInit() {
}
}
El template del componente tampoco tiene ningún detalle a resaltar, puesto que las propiedades se usan igual que hemos visto en anteriores ocasiones.
<p>
Nombre: {{nombre}}
<br>
Cif: {{cif}}
<br>
direccion: {{direccion}}
</p>
Binding de una dirección
Estos datos, tal como se ha dicho, viajan del padre al hijo. Si el padre modifica el valor enviado a las propiedades, también se modificará en el hijo. Lo puedes probar si en el template donde has usado el componente pones un botón para que modifique una de sus propiedades.
<button (click)="cliente.cif='ESB9922'">Cambiar CIF</button>
Al pulsar el botón se modificará el CIF y por tanto cambiará el componente que consumía este dato.
Recuerda que el binding es de una sola dirección, como todos los binding de propiedad expresados con los corchetes. Por tanto, si el hijo modifica la información de la propiedad, el nuevo valor no viajará hacia el padre.
En el siguiente artículo te mostraremos cómo hacer que un dato pueda viajar desde el hijo al padre, usando @Output.
Miguel Angel Alvarez
Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...