Validación de formulario Angular con formularios reactivos y controlados por plantillas
Spanish (Español) translation by Lina (you can also view the original English article)
En este tutorial exploraremos los formularios reactivos y controlados por plantilla en Angular. Verás cómo crear cada tipo y cómo realizar validación en Angular 6.
Formularios reactivos y controlados por plantillas
¿Qué son los formularios reactivos Angular?
Los formularios reactivos también se conocen como formularios controlados por plantillas. Esto significa que el contenido HTML cambia según el código en el componente.
¿Qué son los formularios controlados por plantillas Angular?
Los formularios controlados por plantillas son impulsados por derivados en la plantilla. Esto significa que verás derivados como ngModel
en la plantilla en lugar del código.
Diferencias entre formularios impulsados por plantillas y reactivos
- Los formularios dirigidos por plantillas usan
FormsModule
, mientras que los formularios reactivos usanReactiveFormsModule
. - Los formularios controlados por plantillas son asíncronos, mientras que los formularios reactivos son sincrónicos.
- En los formularios controlados por plantillas, la mayor parte de la interacción se produce en la plantilla, mientras que en los formularios controlados por reactivos, la mayor parte de la interacción se produce en el componente.
Ventajas y desventajas de los formularios controlados por plantillas
Aunque los formularios de plantilla son más fáciles de crear, se convierten en un desafío cuando se quieren hacer pruebas unitarias, porque las pruebas requieren la presencia de un DOM.
Ventajas y desventajas de los formularios reactivos
Es más fácil escribir pruebas unitarias en formularios reactivos, ya que todo el código de formulario y la funcionalidad están contenidos en el componente. Sin embargo, los formularios reactivos requieren más implementación de codificación en el componente.
Crear y validar formularios Angular
En esta sección, veremos cómo crear y validar ambos tipos de formularios. En ambos casos, crearemos un formulario de contacto donde los usuarios pueden enviar datos. Comenzaremos creando una aplicación Angular con dos componentes de la siguiente manera:
ng new angularforms ng generate component reactiveforms ng generate component templateforms
Cómo crear una plantilla de formulario
La plantilla de formulario básico será la siguiente:
<mat-card class="contact-card"> <mat-card-header> <mat-card-title>Template Form</mat-card-title> </mat-card-header> <mat-card-content> <form novalidate > <mat-form-field> <input matInput placeholder="firstname" class="form-control" name="firstname"> </mat-form-field> <br> <mat-form-field> <input matInput placeholder="lastname" class="form-control" name="lastname"> </mat-form-field> <br> <mat-form-field> <input matInput placeholder="email" class="form-control" name="email"> </mat-form-field> <br> <mat-form-field> <textarea rows="4" cols="50" matInput placeholder="message" class="form-control" name="message" ></textarea> </mat-form-field> <br> <button id="submit" mat-raised-button type="submit" color="primary">Submit</button> </form> </mat-card-content> </mat-card>
A continuación, agregaremos el derivado ngModel
a todos los campos como se muestra. Esto es necesario para vincular los campos de entrada a las propiedades del modelo de datos.
<mat-form-field> <input matInput placeholder="firstname" class="form-control" name="firstname" ngModel> </mat-form-field> <br> <mat-form-field> <input matInput placeholder="lastname" class="form-control" name="lastname" ngModel> </mat-form-field> <br> <mat-form-field> <input matInput placeholder="email" class="form-control" name="email" ngModel> </mat-form-field> <br> <mat-form-field> <textarea rows="4" cols="50" matInput placeholder="message" class="form-control" name="message" ngModel></textarea> </mat-form-field>
Luego agregamos los derivados ngForm
y ngSubmit
. ngForm
se activa cuando el usuario hace clic en el botón enviar, mientras que ngSubmit
especifica qué función ejecutar cuando se envía el formulario.
<form novalidate (ngSubmit)="onSubmit()" #f="ngForm"> .. </form>
Luego, importaremos FormsModule
desde @angular/forms
en app.module.ts para activar los formularios controlados por plantilla.
import { FormsModule } from '@angular/forms'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, FormsModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Cuando un usuario ingresa y envía datos y hace clic en el botón Enviar, necesitamos recibir los datos en la clase de componente. Aquí, simplemente registramos los resultados en la consola.
onSubmit(f) { console.log(f.value); }
También puedes ver los datos enviados en tiempo real cuando se escriben valores en el formulario.
<strong>{{f.value.firstname}} </strong> <strong>{{f.value.lastname}} </strong> <strong>{{f.value.email}} </strong> <strong>{{f.value.message}} </strong> </form>
Nuestro formulario ahora está completo y puedes comenzar a realizar las pruebas navegando a http://localhost:4200/template.



Validación de formulario de plantilla Angular
Veamos cómo podemos agregar funciones avanzadas como la validación a nuestro formulario. En este caso, vamos a utilizar algunos validadores incorporados que incluyen:
-
required
: el control de formulario no debe tener un campo vacío. -
MinLength
: el control de formulario debe tener un valor de la longitud mínima especificada. -
MaxLength
: el control de formulario debe tener un valor de la longitud máxima especificada.
-
pattern
: el valor de control de formulario debe coincidir con un valor regex dado.
Empezamos añadiendo el atributo required
a todos los campos de entrada.
<input matInput placeholder="firstname" class="form-control" name="firstname" ngModel required> <input matInput placeholder="lastname" class="form-control" name="lastname" ngModel required> <input matInput placeholder="email" class="form-control" name="email" ngModel required> <textarea rows="4" cols="50" matInput placeholder="message" class="form-control" name="message" ngModel required></textarea>
El botón de envío se validará mediante el uso de la propiedad disabled
, que se establecerá en true
si el formulario es válido.
<button type="submit" [disabled]="f.invalid">Submit</button>
Nuestro formulario de trabajo ahora debe verse como se muestra a continuación. Como puedes ver, el botón Enviar está deshabilitado si no se rellenan todos los campos, y los campos también están marcados con un asterisco para mostrar que son obligatorios.



Creando Formularios Reactivos Angular
Los formularios reactivos Angular también se conocen como formularios dirigidos por modelos. Emplean una técnica en la que los formularios se diseñan en el componente y luego se realizan los enlaces para el HTML. También hacen uso de las siguientes clases disponibles en el módulo ReactiveFormsModule.
-
FormGroup
FormControl
-
FormBuilder
Sólo necesitamos el FormBuilder
API para crear nuestro formulario, ya que nuestro formulario no es complejo. Comenzaremos por importar el módulo en la clase de componente.
import {FormBuilder} from '@angular/forms'
FormBuilder
facilita el andamiaje, especialmente cuando se construyen formularios complejos. Usaremos el método group()
disponible en FormBuilder
para crear la instancia FormGroup
y luego agregar controles de formulario como un objeto.
Luego lo inyectaremos en el constructor mediante inyección de dependencia.
export class ReactiveformsComponent implements OnInit { constructor(private formBuilder: FormBuilder){ } }
Usemos ahora FormBuilder
para construir nuestros modelos de formulario. Actualiza reactiveforms.component.ts para que se vea así:
export class ReactiveformsComponent implements OnInit { form; constructor(private formBuilder: FormBuilder){ this.form = formBuilder.group({ firstname: [''], lastname: [''], email: ['', message: [''], }); } ngOnInit() { } }
En el código anterior, usamos la API de FormBuilder
y agregamos nuestros campos de formulario en un objeto. Ahora podemos implementar la plantilla como un formulario regular. La única diferencia es que tenemos que decirle a Angular cual formGroup
usar.
<mat-card class="contact-card"> <mat-card-header> <mat-card-title>Reactive Form</mat-card-title> </mat-card-header> <mat-card-content> <form id="contactForm" [formGroup]="form" (ngSubmit)="submit()"> <mat-form-field> <input matInput placeholder="firstname" class="form-control" name="firstname"> </mat-form-field> <br> <mat-form-field> <input matInput placeholder="lastname" class="form-control" name="lastname"> </mat-form-field> <br> <mat-form-field> <input matInput placeholder="email" class="form-control" name="email"> </mat-form-field> <br> <mat-form-field> <textarea rows="4" cols="50" matInput placeholder="message" class="form-control" name="message"></textarea> </mat-form-field> <br> <button id="btnSubmit" mat-raised-button type="submit" color="primary">Submit</button> </form> </mat-card-content> </mat-card> <strong>{{form.value.firstname}} </strong> <br> <strong>{{form.value.lastname}} </strong> <br> <strong>{{form.value.email}} </strong> <br> <strong>{{form.value.message}} </strong>
El último bit será implementar la función que decide qué sucede cuando se envía el formulario.
export class ReactiveformsComponent implements OnInit { ngOnInit() { } submit() { if (this.form.valid) { console.log(this.form.value) } else{ alert("FILL ALL FIELDS") } } }
Ahora que nuestro formulario está completo, podemos comenzar a probar. Ve a http://localhost:4200/reactive y, a medida que escribes valores para los campos de entrada, los valores deben aparecer debajo del formulario como se muestra a continuación.



Validación De Formulario Reactivo en Angular
Aún debemos agregar validación a nuestros formularios para asegurarnos de que los usuarios no dejen campos vacíos o ingresen el formato de datos incorrecto.
Primero importaremos el módulo Validators
en el componente. Luego, el módulo se agrega en los campos formGroup
.
constructor(private formBuilder: FormBuilder){ this.form = formBuilder.group({ firstname: ['', Validators.required], lastname: ['', Validators.required], email: ['', [Validators.required, Validators.email]], message: ['', Validators.required], }); }
Queremos que todos nuestros campos sean obligatorios, por lo que actualizaremos nuestros campos con la etiqueta formControlName
, que atiende los cambios en el valor del control.
<form id="contactForm" [formGroup]="form" (ngSubmit)="submit()"> <mat-form-field> <input matInput placeholder="firstname" formControlName="firstname" class="form-control" name="firstname"> </mat-form-field> <br> <mat-form-field> <input matInput placeholder="lastname" formControlName="lastname" class="form-control" name="lastname"> </mat-form-field> <br> <mat-form-field> <input matInput placeholder="email" formControlName="email" class="form-control" name="email"> </mat-form-field> <br> <mat-form-field> <textarea rows="4" cols="50" matInput placeholder="message" formControlName="message" class="form-control" name="message"></textarea> </mat-form-field> <br> <button id="btnSubmit" mat-raised-button type="submit" color="primary">Submit</button> </form>
¡Eso es todo lo que se necesita! Nuestra validación de formulario reactivo Angular ahora está funcionando, como se muestra a continuación.



Conclusión
Este tutorial ha cubierto todos los aspectos básicos de la creación y validación de formularios Angular. Pruébalo y quizás incluso quieras crear tus propias validaciones personalizadas.
El código fuente completo de estos proyectos de ejemplo se puede encontrar en nuestro repositorio de GitHub.