El data binding es el mecanismo con el que Angular mantiene en sincronía la vista renderizada en el navegador y el modelo definido en TypeScript dentro del componente. Cualquier cambio del modelo se refleja en la plantilla y, en el caso bidireccional, cualquier interacción del usuario actualiza el modelo. En Angular 21 el motor de cambio se apoya en signals, valores reactivos que invalidan selectivamente solo las partes del DOM que dependen de ellos.
Binding unidireccional: de componente a vista
El binding unidireccional empuja datos en un único sentido. Es el caso más habitual y cubre la gran mayoría de plantillas. Existen tres formas principales:
Interpolación con dobles llaves {{ }} muestra el valor de una expresión del componente como texto. Si se trata de un signal, se invoca como función dentro de la plantilla.
import { Component, signal } from "@angular/core";
@Component({
selector: "app-saludo",
template: `
<p>Hola, {{ nombre }}</p>
<p>Has visitado {{ visitas() }} veces la pagina</p>
`,
})
export class SaludoComponent {
nombre = "Alba";
visitas = signal(0);
}
Property binding con corchetes [] enlaza una expresión del componente a una propiedad del DOM o a un input de un componente hijo. Resulta útil para controlar atributos dinámicos como disabled, src, alt o inputs personalizados.
@Component({
selector: "app-boton",
template: `
<button [disabled]="procesando()" [class.loading]="procesando()">
Enviar
</button>
<img [src]="avatarUrl()" [alt]="'Avatar de ' + nombre" />
`,
})
export class BotonComponent {
procesando = signal(false);
avatarUrl = signal("/assets/default.png");
nombre = "Alba";
}
Event binding con paréntesis () conecta eventos del DOM con métodos del componente. Es la vía por la que el usuario interactúa con la aplicación: clics, entrada de texto, scroll y eventos personalizados emitidos por componentes hijos.
@Component({
selector: "app-contador",
template: `
<button (click)="incrementar()">Incrementar</button>
<p>Valor actual: {{ valor() }}</p>
`,
})
export class ContadorComponent {
valor = signal(0);
incrementar() {
this.valor.update(v => v + 1);
}
}
La interpolación y el property binding siempre son unidireccionales del componente a la vista. El event binding fluye en sentido contrario: de la vista al componente.
Binding bidireccional con ngModel y model()
El binding bidireccional combina property binding y event binding en una sintaxis doble [()], conocida informalmente como banana-in-a-box. Se aplica a formularios y a componentes personalizados donde padre e hijo comparten estado.
Para formularios tradicionales se utiliza ngModel, que requiere importar FormsModule en el componente standalone:
import { Component, signal } from "@angular/core";
import { FormsModule } from "@angular/forms";
@Component({
selector: "app-buscador",
standalone: true,
imports: [FormsModule],
template: `
<input [(ngModel)]="termino" placeholder="Buscar..." />
<p>Resultados para: {{ termino }}</p>
`,
})
export class BuscadorComponent {
termino = "";
}
En Angular 21, la función model() crea una señal bidireccional en componentes personalizados. Es el mecanismo moderno para comunicar padre e hijo con sincronía automática:
import { Component, model } from "@angular/core";
@Component({
selector: "app-toggle",
standalone: true,
template: `
<button (click)="activo.set(!activo())">
{{ activo() ? "Activado" : "Desactivado" }}
</button>
`,
})
export class ToggleComponent {
activo = model(false);
}
@Component({
selector: "app-panel",
standalone: true,
imports: [ToggleComponent],
template: `
<app-toggle [(activo)]="modoNoche" />
<p>Modo noche actual: {{ modoNoche() }}</p>
`,
})
export class PanelComponent {
modoNoche = signal(false);
}
El componente padre controla el estado modoNoche y el hijo lo actualiza con activo.set(...). El [(activo)] del padre detecta el cambio y propaga el nuevo valor.
flowchart LR
A[Componente TypeScript] -->|Interpolación| B[Vista HTML]
A -->|Property binding| B
B -->|Event binding| A
A -.->|Bidireccional ngModel y model| B
B -.->|Bidireccional ngModel y model| A
La elección entre
ngModelymodel()depende del caso:ngModelsigue siendo la opción natural en formularios, mientras quemodel()brilla en componentes que exponen estado reactivo a su padre.
Caso B2B: panel de control industrial
Una empresa industrial despliega un panel web para que los operarios controlen líneas de producción en fábrica. Cada estación expone un componente EstadoLinea con un signal activa conectado por model() al panel central. Cuando un operario pulsa el botón de parada de emergencia, el signal propaga el cambio al supervisor en tiempo real y la UI refleja el estado sin reloads. La combinación de signals y bindings bidireccionales reduce la latencia percibida por debajo de los 50 milisegundos, incluso en tabletas industriales de gama media usadas en entornos con conectividad limitada.
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Angular es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Angular
Explora más contenido relacionado con Angular y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
- Entender el concepto de data binding y su papel en aplicaciones reactivas.
- Identificar los tipos de binding unidireccional y bidireccional.
- Aplicar interpolación, property binding y event binding con signals y propiedades simples.
- Usar model() y ngModel para comunicación bidireccional moderna.