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 crear 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. Validators: Funciones que se utilizan para validar los controles de formulario.

Configuración Inicial

Para empezar a trabajar con formularios reactivos, primero debemos asegurarnos de que el módulo ReactiveFormsModule esté importado en nuestro módulo principal o en el módulo donde se utilizarán los formularios.

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

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

Creación de un Formulario Reactivo

Paso 1: Definir el Formulario en el Componente

Primero, importamos las clases necesarias desde @angular/forms y definimos nuestro formulario en el componente.

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

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

  ngOnInit() {
    this.myForm = new FormGroup({
      'name': new FormControl(null, [Validators.required, Validators.minLength(3)]),
      'email': new FormControl(null, [Validators.required, Validators.email]),
      'age': new FormControl(null, [Validators.required, Validators.min(18)])
    });
  }

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

Paso 2: Vincular el Formulario en la Plantilla

En el archivo de plantilla HTML, utilizamos las directivas formGroup y formControlName para vincular nuestro formulario reactivo.

<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
  <div>
    <label for="name">Name</label>
    <input id="name" formControlName="name">
    <div *ngIf="myForm.get('name').invalid && myForm.get('name').touched">
      <small *ngIf="myForm.get('name').errors.required">Name is required.</small>
      <small *ngIf="myForm.get('name').errors.minlength">Name must be at least 3 characters long.</small>
    </div>
  </div>

  <div>
    <label for="email">Email</label>
    <input id="email" formControlName="email">
    <div *ngIf="myForm.get('email').invalid && myForm.get('email').touched">
      <small *ngIf="myForm.get('email').errors.required">Email is required.</small>
      <small *ngIf="myForm.get('email').errors.email">Invalid email format.</small>
    </div>
  </div>

  <div>
    <label for="age">Age</label>
    <input id="age" formControlName="age" type="number">
    <div *ngIf="myForm.get('age').invalid && myForm.get('age').touched">
      <small *ngIf="myForm.get('age').errors.required">Age is required.</small>
      <small *ngIf="myForm.get('age').errors.min">You must be at least 18 years old.</small>
    </div>
  </div>

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

Validación de Formularios

Validadores Incorporados

Angular proporciona varios validadores incorporados que se pueden utilizar para validar los controles de formulario. Algunos de los más comunes son:

  • Validators.required: El control es obligatorio.
  • Validators.minLength(length: number): El control debe tener al menos una longitud mínima.
  • Validators.maxLength(length: number): El control debe tener una longitud máxima.
  • Validators.email: El control debe ser un correo electrónico válido.
  • Validators.min(min: number): El control debe tener un valor mínimo.
  • Validators.max(max: number): El control debe tener un valor máximo.

Validadores Personalizados

También podemos crear validadores personalizados para necesidades específicas.

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

export function forbiddenNameValidator(control: AbstractControl): ValidationErrors | null {
  const forbidden = /admin/.test(control.value);
  return forbidden ? { 'forbiddenName': { value: control.value } } : null;
}

Luego, aplicamos el validador personalizado a un control de formulario.

this.myForm = new FormGroup({
  'name': new FormControl(null, [Validators.required, Validators.minLength(3), forbiddenNameValidator]),
  'email': new FormControl(null, [Validators.required, Validators.email]),
  'age': new FormControl(null, [Validators.required, Validators.min(18)])
});

Ejercicio Práctico

Ejercicio

Crea un formulario reactivo con los siguientes campos:

  1. Username: Obligatorio, mínimo 5 caracteres.
  2. Password: Obligatorio, mínimo 8 caracteres.
  3. Confirm Password: Obligatorio, debe coincidir con el campo Password.
  4. Email: Obligatorio, debe ser un correo electrónico válido.

Solución

Componente TypeScript

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

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

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

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

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

Plantilla HTML

<form [formGroup]="signupForm" (ngSubmit)="onSubmit()">
  <div>
    <label for="username">Username</label>
    <input id="username" formControlName="username">
    <div *ngIf="signupForm.get('username').invalid && signupForm.get('username').touched">
      <small *ngIf="signupForm.get('username').errors.required">Username is required.</small>
      <small *ngIf="signupForm.get('username').errors.minlength">Username must be at least 5 characters long.</small>
    </div>
  </div>

  <div>
    <label for="password">Password</label>
    <input id="password" formControlName="password" type="password">
    <div *ngIf="signupForm.get('password').invalid && signupForm.get('password').touched">
      <small *ngIf="signupForm.get('password').errors.required">Password is required.</small>
      <small *ngIf="signupForm.get('password').errors.minlength">Password must be at least 8 characters long.</small>
    </div>
  </div>

  <div>
    <label for="confirmPassword">Confirm Password</label>
    <input id="confirmPassword" formControlName="confirmPassword" type="password">
    <div *ngIf="signupForm.errors?.mismatch && signupForm.get('confirmPassword').touched">
      <small>Passwords do not match.</small>
    </div>
  </div>

  <div>
    <label for="email">Email</label>
    <input id="email" formControlName="email">
    <div *ngIf="signupForm.get('email').invalid && signupForm.get('email').touched">
      <small *ngIf="signupForm.get('email').errors.required">Email is required.</small>
      <small *ngIf="signupForm.get('email').errors.email">Invalid email format.</small>
    </div>
  </div>

  <button type="submit" [disabled]="signupForm.invalid">Submit</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, podemos crear formularios robustos y escalables con validación personalizada. En el siguiente módulo, exploraremos cómo validar y manejar formularios dinámicos en Angular.

Curso de Angular

Módulo 1: Introducción a Angular

Módulo 2: Componentes de Angular

Módulo 3: Enlace de Datos y Directivas

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

Módulo 5: Enrutamiento y Navegación

Módulo 6: Formularios en Angular

Módulo 7: Cliente HTTP y Observables

Módulo 8: Gestión de Estado

Módulo 9: Pruebas en Angular

Módulo 10: Conceptos Avanzados de Angular

Módulo 11: Despliegue y Mejores Prácticas

© Copyright 2024. Todos los derechos reservados