Configuración Inicial

1

¿Vale la pena Aprender Angular?

2

Configura tu entorno de desarrollo en Angular

3

Implementa ESLint para código limpio en Angular

4

Optimiza tu código con Prettier en Angular

Quiz: Configuración Inicial

Gestión de Entornos

5

Gestiona múltiples ambientes de desarrollo

6

Configura entornos Staging para pruebas

Quiz: Gestión de Entornos

Nuevas Funcionalidades en Angular

7

Domina la nueva directiva @let en Angular

8

Optimiza imágenes para mejor rendimiento en Angular

9

Crea URLs amigables para SEO en Angular

10

Implementa Input Signal para componentes reactivos

11

Migra de @Input tradicional a Input Signals

12

Usa la nueva output function para eventos en Angular

13

Sincroniza datos con linkedSignal en Angular

14

Gestiona formularios con Model Signal

15

Convierte Observables a Signals con toSignal

16

Implementa toSignal en componentes

17

Simplifica RxJS con RxResource en Angular

18

Maneja recursos con parámetros usando Resource

19

Optimiza Promises con Resource en Angular

20

Crea consultas reactivas con Signal Queries

21

Resuelve problemas comunes de Prettier en Angular

Quiz: Nuevas Funcionalidades en Angular

Server-Side Rendering (SSR) y Navegación

22

Optimiza tu app con los nuevos builders de Angular

23

Implementa Server-Side Rendering (SSR) en Angular

24

Maneja APIs del navegador en entornos SSR

25

Crea páginas de ubicación optimizadas en Angular

26

Mejora rendimiento con Pre-render en Angular

27

Despliega tu aplicación en Firebase Hosting

Quiz: Server-Side Rendering (SSR) y Navegación

Optimización de Rendimiento

28

Optimiza SEO con títulos y metatags efectivos

29

Implementa MetaTags Service para SEO en Angular

30

Mejora UX con Hydration y EventReplay en Angular

31

Crea productos relacionados con Signals

32

Optimiza rendimiento con @defer en Angular

33

Implementa Hydration incremental para mejor UX

34

Optimiza navegación con Server Routing en Angular

35

Maximiza rendimiento con Zoneless en Angular

36

Siguientes pasos en Angular

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Gestiona formularios con Model Signal

14/36
Recursos

La comunicación entre componentes en Angular es fundamental para construir aplicaciones robustas y escalables. Mientras que los inputs y outputs son mecanismos tradicionales para esta comunicación, Angular ofrece herramientas más avanzadas como el model, que simplifica significativamente la sincronización bidireccional entre componentes padre e hijo. Veamos cómo implementar esta poderosa característica y cómo puede mejorar nuestro flujo de desarrollo.

¿Cómo funciona la comunicación entre componentes en Angular?

La comunicación entre componentes padre e hijo en Angular tradicionalmente se realiza mediante inputs y outputs. Sin embargo, existen situaciones donde necesitamos una sincronización bidireccional más directa. Aquí es donde entra en juego el model, una característica que combina la funcionalidad de input y output en una sola API.

El model funciona de manera similar al conocido ngModel, permitiéndonos enviar datos, ajustarlos y sincronizar valores directamente con el componente padre. Esta característica es especialmente útil cuando necesitamos mantener estados sincronizados entre componentes relacionados.

Limitaciones de los inputs tradicionales

Cuando trabajamos con inputs en Angular, nos encontramos con una limitación importante: no podemos modificar directamente el valor del input desde el componente hijo. Esto tiene sentido desde la perspectiva de la arquitectura de componentes, ya que los inputs están diseñados principalmente para enviar información del padre al hijo, no al revés.

Para ilustrar esta limitación, consideremos un ejemplo con un componente counter que recibe un mensaje como input:

// En el componente counter (hijo)
@Input({ required: true }) message!: string;

// Intentar modificar este valor directamente no es posible
// No podemos hacer: this.message = "Nuevo valor";

Si intentamos crear un método para cambiar este valor:

setMessage() {
  // Esto no funcionará porque message es un input de solo lectura
  this.message = "Nuevo valor";
}

Solución alternativa con signals

Una forma de superar esta limitación es utilizando signals, específicamente con la técnica de computed signals:

// En el componente hijo
@Input({ required: true }) message!: string;

// Creamos una señal derivada que podemos modificar
newMessage = computed(() => this.message);

// Creamos un output para notificar al padre
@Output() changeMessage = new EventEmitter<string>();

setMessage() {
  // Ahora podemos modificar newMessage
  this.newMessage.set("Nuevo valor");
  // Y notificar al padre
  this.changeMessage.emit(this.newMessage());
}

En el componente padre, necesitaríamos:

// En el template del padre
<app-counter 
  [message]="message()" 
  (changeMessage)="onMessageChange($event)">
</app-counter>

// En el componente padre
onMessageChange(newMsg: string) {
  console.log(newMsg);
  this.message.set(newMsg);
}

Esta solución funciona, pero requiere bastante código para algo que debería ser más sencillo.

¿Qué es model y cómo simplifica la comunicación?

Angular ha introducido el decorador @model() precisamente para simplificar este escenario. Este decorador combina la funcionalidad de input y output, permitiendo una sincronización bidireccional automática.

Implementación con model

Para utilizar model, simplemente reemplazamos nuestro input por model:

// En lugar de @Input
@model() message!: string;

Con este cambio, ahora podemos modificar directamente el valor desde el componente hijo:

setMessage() {
  // Ahora esto funciona y se sincroniza automáticamente con el padre
  this.message = "Nuevo valor";
  // O si estamos usando signals
  this.message.set(Math.random().toString());
}

En el componente padre, la sintaxis para usar un componente con model es ligeramente diferente:

<!-- Notar la sintaxis especial que combina [] y () -->
<app-counter [(message)]="message"></app-counter>

<!-- También podemos mostrar el valor sincronizado -->
<p>Parent message: {{ message() }}</p>

Esta sintaxis [(message)] es la notación de "banana in a box" (plátano en caja) que indica una vinculación bidireccional.

Ventajas del uso de model

El uso de model ofrece varias ventajas significativas:

  1. Código más limpio: Elimina la necesidad de crear outputs adicionales y métodos de manejo de eventos.
  2. Sincronización automática: Los cambios en el hijo se reflejan inmediatamente en el padre.
  3. Sintaxis intuitiva: La notación [(property)] es clara y fácil de entender.
  4. Menos propenso a errores: Reduce la posibilidad de errores al eliminar código boilerplate.

¿Cuándo usar cada tipo de comunicación?

Es importante recordar que cada primitiva de comunicación en Angular tiene su propósito específico:

  • Input: Cuando solo necesitas enviar datos del padre al hijo sin modificación.
  • Output: Cuando el hijo necesita notificar eventos al padre.
  • Computed Signal: Cuando necesitas derivar un nuevo valor basado en señales existentes.
  • Model: Cuando necesitas una sincronización bidireccional entre padre e hijo.

No todo tiene que ser model. Elige la herramienta adecuada según el caso de uso específico.

La elección correcta de estas primitivas puede hacer que tu código sea más limpio, más mantenible y más eficiente. El model es particularmente útil cuando tienes formularios o componentes interactivos donde el estado debe mantenerse sincronizado entre componentes relacionados.

Angular continúa evolucionando para ofrecer mejores herramientas a los desarrolladores. En la próxima clase, veremos cómo integrar signals con RxJS mediante la función toSignal, permitiéndonos trabajar con ambos patrones de forma armoniosa.

¿Has utilizado model en tus proyectos de Angular? ¿Qué otros patrones de comunicación entre componentes has encontrado útiles? Comparte tu experiencia en los comentarios.

Aportes 3

Preguntas 0

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

El nombre o título de la clase está mal, porque no estamos gestionando formularios, estamos utilizando el signal model... que es muy diferente...
Justo estaba probando lo primero que dijo nico y me di cuenta de algo curioso, si utilizamos esta primera forma con linkedsignals tenemos que tener en cuenta que al recibir el output en el padre si no modificamos el valor de message queda con el valor anterior: ![](https://static.platzi.com/media/user_upload/image-903e0bbd-58a4-427f-892b-191f2184f2d5.jpg) Entonces haciendo esta moficacion consigo moficar el valor en el padre y en el componente. changeMessage(event: string) { this.$message.set(event); console.log('change Message', event); } ```ts changeMessage(event: string) { this.$message.set(event); console.log('change Message', event); } ```
El decorador `@model()` simplifica la comunicación bidireccional entre componentes, pero **no siempre es la mejor opción**. Si el estado del hijo **no debe modificarse directamente**, sigue usando `@Input()`. Ejemplo: Para valores **calculados o derivados**, es mejor un **computed signal** en lugar de modificar `@model()` directamente. ```ts const formattedMessage = computed(() => `📢 ${this.message()}`); ```Esto mantiene **separación de responsabilidades** y mejora la legibilidad. ¿En qué casos prefieren `@model()` sobre `@Input()` + `@Output()`? 🚀💬