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
- FormGroup: Representa un grupo de controles de formulario.
- FormControl: Representa un control individual de formulario.
- FormArray: Representa una matriz de controles de formulario.
- 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:
- Username: Obligatorio, mínimo 5 caracteres.
- Password: Obligatorio, mínimo 8 caracteres.
- Confirm Password: Obligatorio, debe coincidir con el campo Password.
- 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
- ¿Qué es Angular?
- Configuración del Entorno de Desarrollo
- Arquitectura de Angular
- Primera Aplicación Angular
Módulo 2: Componentes de Angular
- Entendiendo los Componentes
- Creación de Componentes
- Plantillas de Componentes
- Estilos de Componentes
- Interacción entre Componentes
Módulo 3: Enlace de Datos y Directivas
- Interpolación y Enlace de Propiedades
- Enlace de Eventos
- Enlace de Datos Bidireccional
- Directivas Incorporadas
- Directivas Personalizadas
Módulo 4: Servicios e Inyección de Dependencias
- Introducción a los Servicios
- Creación y Uso de Servicios
- Inyección de Dependencias
- Inyectores Jerárquicos
Módulo 5: Enrutamiento y Navegación
Módulo 6: Formularios en Angular
- Formularios Basados en Plantillas
- Formularios Reactivos
- Validación de Formularios
- Formularios Dinámicos
Módulo 7: Cliente HTTP y Observables
- Introducción al Cliente HTTP
- Realizando Solicitudes HTTP
- Manejo de Respuestas HTTP
- Uso de Observables
- Manejo de Errores
Módulo 8: Gestión de Estado
- Introducción a la Gestión de Estado
- Uso de Servicios para la Gestión de Estado
- NgRx Store
- NgRx Effects
- NgRx Entity
Módulo 9: Pruebas en Angular
- Pruebas Unitarias
- Pruebas de Componentes
- Pruebas de Servicios
- Pruebas de Extremo a Extremo
- Simulación de Dependencias
Módulo 10: Conceptos Avanzados de Angular
- Angular Universal
- Optimización del Rendimiento
- Internacionalización (i18n)
- Pipes Personalizados
- Animaciones en Angular
