Inputs y Outputs en Angular

Pasar datos de componentes padres a hijos y de hijos a padres

Una de las cosas que debemos tener en mente en aprender cuando desarrollamos en el frontend es cómo pasar los datos entre componentes y a nivel lógico cómo pasarlos entre padres a hijos y de hijos a padres ya que ese flujo de datos nos va ayudar a definir componentes de una forma organizada en el proyecto y también ayudará a ejecutar un soporte adecuado del mismo en el transcurso del tiempo.
En Angular conozco un par de formas: Inputs (de padres a hijos) Outputs (de hijos a padres) y a través de un store, este último caso lo veremos luego.
Para estos ejemplos vamos a usar el proyecto explicado En el tutorial anterior
Vamos a components/plates/plates.component.html. Podemos observar dos cosas, de la linea 1 a la 21 un acordión de AngularMaterial que lleva dentro de él un pequeño formulario para guardar y editar los platos.
Luego, entre las lineas 22 a 26 tenemos app-plates-list, es decir, el componente hijo. Podemos observar que tiene una configuración especial y con ello parte de las funcionalidades de envío y recepción de datos.
Ahora, vamos a explicar cada uno de los procesos:
Inputs: ¿Cómo comienza el flujo de datos? en la linea 18 podemos ver la función createPlate() y dicha función nos permite envíar datos al controlador y agregarlos al input tipo FormControl. FormControl es una funcionalidad de @angular/forms y nos permite usar componentes reactivos para nuestros formularios.
Ahora bien, recordemos que este proyecto está en base a Firebase, por lo tanto debemos integrar sus funciones a nuestros controladores e inyectar sus dependencias para usar sus funciones. Este caso particular divide el proceso en dos, identificar si la acción del formulario es para registrar un nuevo plato o si es para actualizar un plato existente. No entro más en detalle para no perder el hilo de lo que necesitamos comprender para este post.
angular1
angular2
¿Cuál es la idea? guardar un plato y visualizarlo de forma reactiva en nuestra tabla que lista los platos (componente hijo) entonces veamos:
Luego de que firebase en este caso guarde los datos nosotros necesitamos configurar un proceso que permita visualizar dichos datos. Entonces, en el constructor de nuestro componente llamamos la colección de platos y se la pasamos a una variable plates. plates es un array tipo observable. ¿Por qué observable? porque firestore (en este caso la DB que estamos usando de firebase) va devolver siempre un observable y como estamos escribiendo en Typescript debemos definirlo como tal. Luego en nuestra vista configuramos un key mediante el cual vamos a pasarle ese array a nuestro componente hijo. Pueden ver las lineas 22 y 29 del constructor. Linea 25 del template.
angular3
angular4
En nuestro componente hijo (lista de platos) definimos en la linea 11 @Input() plates: any[]; Input es un módulo de @angular/core y plates es el key que definimos en el template del componente padre. Allí entonces, estamos recibiendo la lista de platos. En la función ngOnChanges pasamos esa lista dataSource que es una variable tipo MatTableModule y que va permitir la visualización del mismo a través del template. En el template simplemente accedemos a los keys de dicho array. Estos items están en la docu de Angular Material. Pueden ver las lineas 11 y 17 del controlador.
angular5
angular6
Entonces en resumen. Configuramos nuestro componente padre, definimos los tipos de datos en nuestros controladores y pasamos a través del componente hijo definido en el template del padre un key y su respectivo value. En el componente hijo definimos una variable tipo Input que va recibir dicho dato.
Outputs: ¿Qué necesitamos en este caso? en la tabla de platos tenemos un botón tipo pencil, este botón envía los datos del componente hijo (la tabla que lista los platos) al componente padre (el formulario) entonces configuramos lo siguiente en el componente hijo:
EventEmitter y Output de @angular/core nos permite ejecutar este proceso, entonces los definimos de la siguiente manera: En la linea escribimos un Output tipo EventEmitter llamado plateEvent, esta variable va comunicarse con nuestro componente padre. Esto lo podemos ver en la linea 12
angular7
En nuestro template definimos la función a ejecutar cuando el usuario da click sobre el botón tipo pencil, esto lo podemos ver en la linea 13
angular8
Después en nuestro controlador definimos la función addPlateToForm(value: string) que va recibir el value que se le envía desde el form y se accede a la función emit (ya que plateEvent es un Output tipo EventEmitter) Esto de forma concreta envía el dato al componente padre. Pueden ver la linea 22
angular9
Ahora bien, para terminar de comprender el flujo de datos volvamos al template del componente padre donde tenemos definido el componente hijo en la linea 23, vemos que configuramos el key del Output tipo EventEmitter definido en el hijo con la función addPlateToForm($event) que es la que se encarga finalmente de colocar el dato en el formulario.
angular10
angular11
Y listo! ya estudiamos como pasar datos entre componentes padres e hijos con Angular.
Pueden clonar el proyecto AQUÍ
Pueden ver el proyecto en producción AQUÍ
Espero que les sirva, saludos!
#Typescript
#Angular
#Components
#Inputs
#Outputs
Comentarios: Pronto!