Para poder seguir este artículo es necesario crear un proyecto de Angular y arrancarlo. Si necesitas más información de cómo crear y arrancar un proyecto te aconsejo visitar el siguiente enlace: Instalando Angular, creando un proyecto y arrancándolo en local

En este artículo os vamos a presentar a la comunicación entre componentes y además nos centraremos en como comunicar componentes, concretamente hablaremos sobre la comunicación desde un componente padre hacía un componente hijo mediante a la propiedad Input Property y su decorador @Input. También, trabajaremos con alias sobre nuestro decorador @Input. ¡Si os parece, comenzamos!

Tipos de comunicación entre componentes

Como ya hemos visto anteriormente, Angular se basa en componentes, y en muchas ocasiones nos puede surgir la necesidad de realizar comunicaciones entre nuestros componentes con el fin de que interactúen entre ellos y poder de esta forma traspasar datos de nuestro componente principal hacía el secundario o viceversa. Para realizar dichas acciones surgen las propiedades input Property (que utilizará el decorador @Input) y output Property (que utilizará el decorador @Output).

Ya hemos visto que tenemos dos tipos de comunicaciones vamos a explicarlas más al detalle:

  • Comunicación del componente padre (principal) hacía el componente hijo (secundario).
      • Utilizamos Input Property mediante al decorador @Input
  • Comunicación del componente hijo (secundario) hacía el componente padre (principal).
      • Utilizamos Output Property mediante al decorador @Output

Creando el componente hijo

Bien, para trabajar con nuestros componentes vamos a generar primeramente el componente hijo:

Ahora tenemos dos componentes en nuestra aplicación el componente padre (app.component.ts) y el componente hijo (hijo.component.ts)

Asociando el componente hijo con el componente padre

Si vamos al componente hijo podemos ver su selector (el nombre del componente que utilizaremos para añadirlo al componente padre), su template (el HTML), y su hoja de estilo (CSS en nuestro caso).

Vemos que en la vista del componente hijo tenemos el siguiente texto:

Si me meto en componente padre y modifico el contenido de su template, podemos ver cuál es su template:

Y modificarla añadiéndole un h1 junto al selector (nombre) del componente hijo:

Si ahora probamos nuestra aplicación de Angular, podemos ver que funcionan correctamente, aunque, por el momento no se están comunicando entre sí:

Comunicación de padre a hijo (@Input)

Para poder realizar la comunicación mediante a input Property necesitamos:

  • Crear la variable o el objeto (en nuestro caso usuarioInparent) que vamos a enviar hacía el componente hijo en la clase padre (app.component.ts)
  • Importar en la clase hija la interfaz Input de @angular/core. Como ya tenemos un import para otros elementos de está librería, podemos añadir este import dentro.
  • Definir el decorador @Input junto al nombre que recibirá la variable hija.
  • Ir a la vista del componente padre (app.component.html) y dentro de la llamada al componente mediante a su decorador, vamos a utilizar el Property Binding para asignar [variableHija] = «variablePadre». Se pueden llamar iguales, pero no las hemos llamado igual para que veáis mejor cual es la variable del componente hijo y cuál es la variable del componente padre.

Si vamos al navegador, podemos ver que nos aparece el nombre del usuario dentro del componente hijo:

De hecho, si inspeccionamos la aplicación de Angular, podemos ver que tenemos el elemento p que contiene el dato dentro del componente app-hijo.

Añadiendo Get & Set

Aunque ya nos está funcionando perfectamente, podemos ver que en la clase padre nos aparece una bombilla, si pulsamos encima, nos ofrece la posibilidad de generar el ‘get’ y el ‘set’.

Si le pulsamos encima, y editamos un poco el Get y el Set, el resultado será:

Configurando tslint.json

Con el private, le indicamos a la variable que solo será visible a nivel de nuestra clase. Y aunque la barra baja «_» es opcional, nos sirve a modo de convención para indicar que la variable solo será visible a nivel de la clase.

Pero pese a que nos compila correctamente:

Podemos ver que nos salta una advertencia de que «variable name must be in loverCamelCase, PascalCasa or UPPER_CASE (variable-name)».

Para resolver este problema vamos a tslint.json, que como ya sabemos es el archivo donde configuramos el conjunto de reglas que definirán que está permitido y que no en la sintaxis de nuestro código de TypeScript.

Y dentro de la pestaña rules, y tenemos que buscar la "variable-name" (la encargada de comprobar los nombres de las variables en busca de errores de sintaxis) y definir la regla o el conjunto de reglas que queremos permitir. Por defecto podemos ver que tenemos:

El conjunto de reglas que podemos definir son:

  • «check-format»: habilita la aplicación de un determinado formato de nomenclatura. De forma predeterminada, la regla solo permite nombres de variable lowerCamelCased o UPPER_CASED.
  • «require-const-for-all-caps»: obliga a que todas las variables con nombres UPPER_CASED sean const.
  • «ban-keywords»: no permite el uso de determinadas palabras clave de TypeScript como nombres de variables o parámetros.
      • Estos son: any, Number, number, String, string, Boolean, boolean, Undefined,undefined
  • «allow-pascal-case»: permite PascalCase además de lowerCamelCase.
  • «allow-leading-underscore»: permite guiones bajos al principio (solo tiene efecto si se especifica «formato de verificación»)
  • «allow-pascal-case»: permite PascalCase además de lowerCamelCase.
  • «allow-snake-case»: permite snake_case además de lowerCamelCase.
  • «allow-trailing-underscore»: permite guiones bajos al final. (solo tiene efecto si se especifica «formato de verificación»).

En nuestro caso, usaremos la allow-leading-underscore ya que queremos definir guiones bajo al principio de la variable. Si lo cambiamos, podemos ver que ha dejado de quejarse en el archivo app.component.ts

Siguiendo con la encapsulación del component hijo

Si ahora miramos el resultado, podemos ver que estamos trabajando con una variable encapsulada en ambos componentes sobre las que solamente podemos obtener el valor que contienen mediante a sus Getters sin además permitirnos modificar sus valores a excepción de si usamos sus métodos Setters.

Si vamos al navegador y miramos nuestra aplicación, podemos ver que el resultado es el mismo:

Declarando un Alias en @Input

Para explicar el concepto de alias, primero vamos a quitar el Get y el Set de nuestra propiedad. Y posteriormente, una vez entendido el concepto explicaremos como resolverlo también con Get y Set.

Si vamos a nuestro componente hijo, y modificamos el nombre que hemos definido anteriormente en nuestro decorador @Input, pero no lo hacemos en el Property Binding de nuestro archivo app.component.html ni en el String interpolation de nuestro template hijo.component.html, podemos ver que cuando se realiza la transpilación Angular nos peta y nos da un error diciendo que usuarioInChild no se encuentra dentro del componente app-hijo:

Un mecanismo para arreglarlo podría ser, el modificar del Property biding del template app.component.html además del de nuestro template sobre el que usamos String Interpolation. El resultado será:

Otra alternativa a esto es utilizar alias, que consiste en renombrar la variable dentro del decorator input. Vamos a ver un ejemplo:

Pero pese a ello, vemos que nos aparece una línea amarilla debajo de nuestro código, ya podemos imaginarnos que es (el verificador de sintaxis tslint.json) ¿Qué regla nos hemos saltado? In the class "HijoComponent", the directive input property "elUsuarioInChild" should not be renamed.
However, you should use an alias when the directive name is also an input property, and the directive name
doesn't describe the property. In this last case, you can disable this rule with `tslint:disable-next-line:no-input-rename`.
(no-input-rename)

Para solventarlo vamos al tslint y buscamos la propiedad no-input-rename (con Control + F situados en el documento)

Y modificamos su valor de true a false:

Si miramos el archivo, podemos ver que ahora sí que funciona correctamente y que solamente hemos tenido que modificar los componentes hijos donde usamos String interpolation. Aunque ni yo ni tslint.json somos partidarios de utilizar alias, por ello nos lo muestra como deshabilitado, gracias a los alias, podemos evitar tener que editar los componentes sobre los que este asociado con Property Biding. Y solamente tener que editar nuestro componente hijo.


Si lo complicamos un poco más esto, aunque si entendemos el concepto será sencillo, podemos cambiar el nombre de ambos métodos sin mucho problema. El método en rojo será nuestro set y el método en verde nuestro get mediante al cual hacemos una llamada desde nuestro template en hijo.component.html:

Esto es todo por hoy, espero que os haya gustado. Un saludo 🙂