Tradicionalmente, Angular ha utilizado la directiva ngModel
para conseguir la vinculación bidireccional de datos.
La directiva [(ngModel)]
es una forma abreviada de vincular la propiedad value del elemento input (u otro elemento de formulario) a una propiedad en el componente, y emitir cambios desde el input de vuelta al componente, manteniendo el estado del componente actualizado.
La nueva función de modelo hace algo similar donde los cambios en el componente hijo se reflejan en el componente padre sin necesidad de un emisor de eventos @Output
.
Angular Model Inputs aprovecha el sistema de señales de Angular para la reactividad, haciendo la vinculación de datos más simple y más declarativa.
En este artículo, explicaremos cómo utilizar las entradas de modelo de forma efectiva, en qué se diferencian de las entradas de señal normales y por qué suponen un cambio radical para tus aplicaciones Angular.
¿Qué es una Entrada Modelo? (Angular Models)
Model Input es una señal de entrada que se puede escribir, lo que significa que su valor se puede cambiar desde cualquier lugar utilizando los métodos set y update.
Soporta enlace de datos bidireccional, lo que significa que el componente hijo puede enviar actualizaciones al padre, y viceversa.
En Angular estándar:
Una comunicación padre-hijo se consigue usando @Input()
(enlace de datos unidireccional).
Una comunicación de hijo a padre requiere @Output()
y un EventEmitter
.
@Input() value!: string; // One-way data binding.
@Output() valueChange = new EventEmitter<string>(); // Send changes back.
Esta configuración es engorrosa para la vinculación bidireccional de datos.
Model Inputs simplifica esto combinando ambas funcionalidades en la función model()
.
La función model reduce el código repetitivo necesario con @Output()
y EventEmitter
, haciendo que la vinculación bidireccional sea más sencilla y declarativa.
Model Inputs utiliza la sintaxis [( )]
(conocida como el plátano en una caja) para la vinculación bidireccional para lograr la sincronización entre un componente padre y un componente hijo.
Ejemplo práctico
Veamos cómo se comporta en la práctica:
1. Componente padre (app.component.ts)
En el componente padre, enlazas valores usando la sintaxis de enlace bidireccional de Angular [(property)]
.
import { Component } from "@angular/core";
import { ExampleComponent } from "./example/example.component";
@Component({
selector: 'app-root',
template: `
<app-example [(checked)]="parentChecked" [disabled]="parentDisabled"></app-example>
<p>Checked in Parent: {{ parentChecked }}</p>
`,
imports: [ExampleComponent]
})
export class AppComponent {
parentChecked = false; // Initial value for two-way binding.
parentDisabled = true; // Read-only input.
}
2. Componente hijo (example.component.ts):
Si se activa en el hijo, el padre se actualiza automáticamente.
import { Component, input, model } from "@angular/core";
@Component({
selector: 'app-example',
template: `
<button (click)="toggle()">Toggle Checked</button>
<p>Checked: {{ checked() }}</p>
<p>Disabled: {{ disabled() }}</p>
`
})
export class ExampleComponent {
checked = model(false);
disabled = input(false);
toggle() {
this.checked.set(!this.checked());
}
}
Explicación de cómo funciona
De padre a hijo:
El padre establece el valor de checked y disabled.
El hijo recibe estos valores a través de model()
y input()
.
De hijo a padre:
El hijo modifica el valor de checked mediante model()
.
El padre es notificado de los cambios en checked automáticamente.
Conclusión
Las entradas de modelo simplifican la vinculación bidireccional de datos eliminando la necesidad de @Output()
y EventEmitter
en los componentes hijo.
Permiten un código más declarativo, que es más fácil de mantener y reduce la repetición de código.
Además, aprovechan el sistema de señales de Angular para la reactividad, lo que mejora el rendimiento mediante la gestión eficiente de los cambios. Si aún no lo has probado, esta es una gran característica para explorar e integrar en tus proyectos.