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

Hasta ahora, hemos estado trabajando con comunicaciones/sincronizaciones (bindings) unidireccionales, es decir, de una sola dirección, los conocidos como One Way Data Binding.

En los que nos traspasábamos/comunicábamos/sincronizábamos un objeto o una variable de nuestra Modelo, es decir, la lógica de negocio del componente situado en nuestro código de TypeScript hacía el template (el HTML) o viceversa.

En esta gráfica podemos ver más detalladamente hacía que dirección trabaja cada uno de los bindings. Y podemos ver que hay bindings trabajan del componente hacía la vista todos los que hemos explicado a excepción del Event Binding que trabaja de la vista hacía el componente.

Si por ejemplo dentro del data binding, utilizamos interpolation binding (englobado dentro del one-way binding) podemos escribir un párrafo y podemos ver que es el TypeScript el que envía la información hacía el template:

Si ampliamos nuestro ejemplo, podemos ver que tenemos un párrafo junto a un input ambos con el mismo nombre. Podemos ver que hemos trabajado con String interpolation binding y property binding.

En el hipotético caso que queramos modificar el valor del input, podemos comprobar que el nombre del saludo no se nos modifica:

Esto es debido a que con String Interpolation, solamente podemos sincronizar la información del componente hacía la vista.

Pero lo podemos arreglar realizando un evento y a través del objeto $event, asignar el nuevo valor a la variable cada vez que se modifique dicha variable.

Otra manera de realiza resto es mediante a template view. Vamos a verlo:

Con esto estamos utilizando la bidireccionalidad gracias a dos binding unidireccionales y, por tanto, con el binding de String Interpolation sincronizamos el valor del Componente hacía nuestro Template. Y con el evento, asignamos el valor a la variable. El resultado de ambas, será el siguiente:

En este ejemplo hemos tenido que trabajar con string interpolation para asignar el valor, y con Property Binding [] y Event binding ().

Lo que realmente hace ngModel es hacer ambas cosas a la vez:

¿Qué es Two-way binding?

Two-way binding es el mecanimos mediante el cual vamos a vamos a realizar comunicaciones/sincronizaciones (bidings) bidireccionales, es decir, del template al Modelo y del modelo al template a la vez.

Existen tres formas de trabajar con ngModel:

  • [ngModel] de esta forma estamos utilizándolo mediante a Property Binding. Si utilizamos ngModel de esta manera el binding será unidireccional, es decir, One-way Binding. Envia el valor de forma unidireccional desde el Modelo (el código de TypeScript de nuestro componente) hasta la template (vista HTML de nuestro componente).

Y podemos ver que nuestro input tiene el valor que tenemos asignado a nuestra variable String de nuestro código de TypeScript.

  • (ngModel) de esta forma lo estamos utilizando como un Event Binding. Si utilizamos ngModel de esta manera el binding será unidireccional, es decir, One-way Binding. Envía el valor de forma unidireccional desde el template (vista HTML de nuestro componente) hacía el Modelo (el código de TypeScript de nuestro componente).

Pero si ejecutamos el código, vemos que ejecuta el valor, pero no cambia su valor:

Problemas de trabajar con ngModel desde [] o ()

Si nos fijamos trabajar con ngModel unidireccional, no nos permite hacer lo que queríamos. Para ello, tendremos que utilizar ambos, aunque de una forma algo más compleja que la forma bidireccional que veremos a continuación posteriormente de explicar cómo combinar ambos ngModels unidireccionales.

Si ahora añadió otro console log con el valor del evento (target.value):

Podemos ver que el valor lo recibe correctamente:

¿Que nos faltaría? Pues asignar el valor capturado en el evento en nuestra variable nombre. Lo podemos hacer de dos maneras:

  1. La primera manera sería modificando el valor desde una función en el TypeScript:

Y si ahora, modificamos nuestro input, podemos ver que inicialmente vale David, y posteriormente, yo asigno el valor del evento que cambiará el valor de String interpolation del h1 y mostrará un mensaje por consola.

Pero para ello, hemos tenido que crear una función asignarle un evento, asignar el valor del dicho evento a la nueva variable y puede resultar un poco complejo.

2. La segunda manera ya la vimos anteriormente sería:

  • [(ngModel)] de esta forma estamos combinando un Event Biding con un Property Biding. Si utilizamos ngModel de esta manera el binding será bidireccional, es decir, Two-way Binding y la combinación de un evento junto a una propiedad nos otorga mucho potencial que se traducirá en que nos facilitará mucho la vida.

Para no olvidarnos de su sintaxis os voy a dar un pequeño tip, se suele utilizar el término de caja de plátanos, por la similitud que tiene los corchetes () con una banana y los [] con la caja donde guardamos los plátanos.

Utilizamos el binding de ngModel bidireccional para escuchar eventos y actualizar los valores simultáneamente entre el template y el modelo de nuestro componente.

Vamos a ver un ejemplo:

Solucionando el error: Can’t bind to ‘ngModel’ since it isn’t a know property of ‘input’

Pero al realizar la compilación nos aparece el siguiente error:

Esto se produce debido a que necesitamos ir al módulo que contiene a dicho componente. En nuestro caso, cuando creamos un proyecto inicialmente dicho módulo será app.module.ts. Lo podemos comprobar situándonos en dicho módulo y mirando si dicho componente está contenido dentro del array de declaraciones (declaraction).

Una vez tenemos el módulo sobre el que trabaja nuestro componente, vamos a realizar el import de otro módulo que necesitamos para trabajar con ngModel de forma bidireccional.

Dicho módulo que vamos a importar se llama FormsModule y se encuentra dentro de @angular/forms. Además de importar el módulo , lo tendremos que añadir al array de imports:

Perfecto, si volvemos a mirar la transpilación (compilación) de nuestro proyecto, podemos ver que ahora se ha realizado correctamente:

Si ahora escribimos en nuestro input, podemos ver que solamente escribiendo [(ngModel)] se nos ha hecho todo lo que habíamos hecho anteriormente manualmente nosotros:

Vemos que el resultado sincroniza tanto el valor del template hacía el TS y además modifica el valor del template constantemente de forma reactiva.

Ejercicio ejemplo selecciona un deporte

Bien, ya hemos visto como trabajar con ngModel bidireccional.

Ahora, vamos a ver un ejemplo que en un futuro, nos puede ser más útil. Quiero seleccionar un deporte sobre un listado contenido en un select. El resultado será:

Si vamos al navegador, podemos ver que nos indica que seleccionemos un deporte:

Si seleccionamos Basquet, el valor que se mostrará en el string interpolation del H1 será el valor definido dentro del value del option:

Y muestra de que el value es el que define el valor, es que hemos escrito el value de Hockeyyy con 3 Y en el hipotético caso que seleccionamos Hockey, podemos ver que el valor será Hockeyyy:

Esto es debido a que es bastante frecuente, el usar una descripción que no tiene nada que ver con los values que por ejemplo podrían ser 1, 2, 3, etc.

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