Introducción

Los formularios reactivos en Angular proporcionan una forma más robusta y escalable de manejar formularios en comparación con los formularios basados en plantillas. Utilizan una aproximación programática para construir y gestionar formularios, lo que permite un mayor control sobre la validación y el estado del formulario.

Conceptos Clave

  1. FormGroup: Representa un grupo de controles de formulario.
  2. FormControl: Representa un control individual de formulario.
  3. FormArray: Representa una matriz de controles de formulario.
  4. FormBuilder: Servicio que facilita la creación de instancias de FormGroup, FormControl y FormArray.

Configuración Inicial

Antes de comenzar, asegúrate de que el módulo ReactiveFormsModule esté importado en tu módulo principal o en el módulo donde vayas a utilizar formularios reactivos.

import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    // otros módulos
    ReactiveFormsModule
  ],
  // otros metadatos
})
export class AppModule { }

Creación de un Formulario Reactivo

Paso 1: Importar las Clases Necesarias

Primero, importa las clases necesarias desde @angular/forms.

import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';

Paso 2: Definir el Formulario en el Componente

Define el formulario en tu componente. Aquí hay un ejemplo de un formulario simple con dos campos: nombre y correo electrónico.

@Component({
  selector: 'app-reactive-form',
  templateUrl: './reactive-form.component.html'
})
export class ReactiveFormComponent {
  myForm: FormGroup;

  constructor() {
    this.myForm = new FormGroup({
      name: new FormControl('', [Validators.required, Validators.minLength(3)]),
      email: new FormControl('', [Validators.required, Validators.email])
    });
  }

  onSubmit() {
    console.log(this.myForm.value);
  }
}

Paso 3: Crear la Plantilla del Formulario

Crea la plantilla del formulario en el archivo HTML correspondiente.

<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
  <label for="name">Nombre:</label>
  <input id="name" formControlName="name">
  <div *ngIf="myForm.get('name').invalid && myForm.get('name').touched">
    <small *ngIf="myForm.get('name').errors.required">El nombre es obligatorio.</small>
    <small *ngIf="myForm.get('name').errors.minlength">El nombre debe tener al menos 3 caracteres.</small>
  </div>

  <label for="email">Correo Electrónico:</label>
  <input id="email" formControlName="email">
  <div *ngIf="myForm.get('email').invalid && myForm.get('email').touched">
    <small *ngIf="myForm.get('email').errors.required">El correo electrónico es obligatorio.</small>
    <small *ngIf="myForm.get('email').errors.email">El correo electrónico no es válido.</small>
  </div>

  <button type="submit" [disabled]="myForm.invalid">Enviar</button>
</form>

Validación de Formularios

La validación en formularios reactivos se maneja a través de validadores que se pueden aplicar a los controles de formulario. Angular proporciona varios validadores incorporados como Validators.required, Validators.minLength, Validators.maxLength, Validators.email, etc.

Validadores Personalizados

También puedes crear validadores personalizados. Aquí hay un ejemplo de un validador personalizado que verifica si un nombre contiene solo letras.

import { AbstractControl, ValidationErrors } from '@angular/forms';

export function onlyLettersValidator(control: AbstractControl): ValidationErrors | null {
  const valid = /^[a-zA-Z]+$/.test(control.value);
  return valid ? null : { onlyLetters: true };
}

Luego, puedes usar este validador en tu formulario.

this.myForm = new FormGroup({
  name: new FormControl('', [Validators.required, Validators.minLength(3), onlyLettersValidator]),
  email: new FormControl('', [Validators.required, Validators.email])
});

Ejercicio Práctico

Ejercicio

Crea un formulario reactivo con los siguientes campos:

  • Nombre de usuario (obligatorio, mínimo 5 caracteres)
  • Contraseña (obligatorio, mínimo 8 caracteres)
  • Confirmar contraseña (debe coincidir con la contraseña)

Solución

  1. Componente TypeScript
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'app-signup-form',
  templateUrl: './signup-form.component.html'
})
export class SignupFormComponent {
  signupForm: FormGroup;

  constructor() {
    this.signupForm = new FormGroup({
      username: new FormControl('', [Validators.required, Validators.minLength(5)]),
      password: new FormControl('', [Validators.required, Validators.minLength(8)]),
      confirmPassword: new FormControl('', [Validators.required])
    }, { validators: this.passwordMatchValidator });
  }

  passwordMatchValidator(form: FormGroup) {
    return form.get('password').value === form.get('confirmPassword').value ? null : { mismatch: true };
  }

  onSubmit() {
    console.log(this.signupForm.value);
  }
}
  1. Plantilla HTML
<form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
  <label for="username">Nombre de Usuario:</label>
  <input id="username" formControlName="username">
  <div *ngIf="signupForm.get('username').invalid && signupForm.get('username').touched">
    <small *ngIf="signupForm.get('username').errors.required">El nombre de usuario es obligatorio.</small>
    <small *ngIf="signupForm.get('username').errors.minlength">El nombre de usuario debe tener al menos 5 caracteres.</small>
  </div>

  <label for="password">Contraseña:</label>
  <input id="password" type="password" formControlName="password">
  <div *ngIf="signupForm.get('password').invalid && signupForm.get('password').touched">
    <small *ngIf="signupForm.get('password').errors.required">La contraseña es obligatoria.</small>
    <small *ngIf="signupForm.get('password').errors.minlength">La contraseña debe tener al menos 8 caracteres.</small>
  </div>

  <label for="confirmPassword">Confirmar Contraseña:</label>
  <input id="confirmPassword" type="password" formControlName="confirmPassword">
  <div *ngIf="signupForm.errors?.mismatch && signupForm.get('confirmPassword').touched">
    <small>Las contraseñas no coinciden.</small>
  </div>

  <button type="submit" [disabled]="signupForm.invalid">Registrarse</button>
</form>

Conclusión

Los formularios reactivos en Angular proporcionan una forma poderosa y flexible de manejar formularios complejos. Al utilizar FormGroup, FormControl y validadores, puedes crear formularios robustos y altamente personalizables. En el siguiente tema, exploraremos la validación de formularios en mayor detalle, incluyendo validadores asíncronos y mensajes de error personalizados.

Curso de Angular 2+

Módulo 1: Introducción a Angular

Módulo 2: Conceptos Básicos de TypeScript

Módulo 3: Componentes y Plantillas

Módulo 4: Directivas y Pipes

Módulo 5: Servicios e Inyección de Dependencias

Módulo 6: Enrutamiento y Navegación

Módulo 7: Formularios en Angular

Módulo 8: Cliente HTTP y Observables

Módulo 9: Gestión de Estado

Módulo 10: Pruebas en Angular

Módulo 11: Temas Avanzados

Módulo 12: Despliegue y Mejores Prácticas

© Copyright 2024. Todos los derechos reservados