CodeForge

Angular 21 de Cero a Experto / Formularios

Formularios: template-driven vs reactivos

Teoría20 min20 XP

Los formularios son la puerta por la que entran los datos a tu app: crear un gasto, editar un perfil, iniciar sesión. Angular ofrece DOS formas de construirlos —template-driven y reactivos— y elegir bien marca la diferencia entre un formulario que se mantiene solo y uno que se vuelve un nudo. Hoy entiendes ambos enfoques, sus fortalezas, y por qué los reactivos son el estándar para todo lo que no sea trivial.

Dos formas de llevar las cuentas

Enfoque template-driven: la lógica vive en el HTML

Con el enfoque template-driven, el formulario se define en el template con directivas (ngModel), y Angular construye el modelo por detrás. Es rápido para formularios pequeños:

login-simple.component.ts
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';

@Component({
selector: 'app-login',
imports: [FormsModule],   // ngModel vive aquí
template: `
  <form #f="ngForm" (ngSubmit)="entrar()">
    <input name="email" [(ngModel)]="email" required email />
    <input name="clave" [(ngModel)]="clave" required minlength="6" />
    <button [disabled]="f.invalid">Entrar</button>
  </form>
`,
})
export class LoginComponent {
email = '';
clave = '';
entrar() { console.log(this.email, this.clave); }
}

La validación se declara con atributos HTML (required, minlength), y #f="ngForm" te da el estado del formulario. Es conciso, pero toda la lógica está atada al template: cuesta testear, reutilizar validaciones y manejar formularios complejos o dinámicos.

Enfoque reactivo: el formulario es un objeto en tu clase

Con el enfoque reactivo, defines la estructura del formulario en la CLASE con objetos (FormGroup, FormControl), y el template solo se conecta a ellos. El modelo es explícito, tipado y testeable:

login-reactivo.component.ts
import { Component, inject } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';

@Component({
selector: 'app-login',
imports: [ReactiveFormsModule],
template: `
  <form [formGroup]="form" (ngSubmit)="entrar()">
    <input formControlName="email" />
    <input formControlName="clave" type="password" />
    <button [disabled]="form.invalid">Entrar</button>
  </form>
`,
})
export class LoginComponent {
private fb = inject(FormBuilder);

form = this.fb.group({
  email: ['', [Validators.required, Validators.email]],
  clave: ['', [Validators.required, Validators.minLength(6)]],
});

entrar() { console.log(this.form.value); }
}

Aquí el formulario es un OBJETO (form) que vive en tu clase: puedes leerlo, validarlo, transformarlo y testearlo sin tocar el DOM. La validación es código (arrays de validadores), no atributos HTML. Esta separación es lo que hace a los reactivos escalar.

Cuándo cada uno

Un puente con lo que ya sabes

Si vienes de React, el enfoque reactivo te resultará familiar: es como manejar el estado del formulario tú mismo con useState/React Hook Form (el modelo vive en tu código), mientras que template-driven se parece más a los inputs no controlados con validación por atributos HTML. La ventaja de Angular es que trae un sistema de formularios reactivos completo de fábrica —validadores, estados, arrays dinámicos— sin instalar nada.

¿Por qué los formularios reactivos escalan mejor que los template-driven?

Mini-reto

Para cada formulario, decide qué enfoque usarías y por qué: 1) un campo de búsqueda en la barra superior; 2) el formulario de "nuevo gasto" con validación de monto positivo y categoría obligatoria; 3) un formulario de encuesta donde el número de preguntas cambia según respuestas anteriores; 4) un toggle de "modo oscuro". Anota cuál lógica de validación necesitaría cada uno.

Qué sigue

Elegiste el enfoque reactivo para lo que importa. La próxima lección lo construye a fondo: FormGroup, FormControl y FormBuilder, con el tipado estricto que Angular moderno trae de fábrica —para que el valor de tu formulario sea un objeto con tipos, no un any—.