93 - Formularios reactivos - FormBuilder

La clase FormBuilder nos permite crear objetos de la clase FormGroup y FormControl con una sintaxis más corta. Es decir que el resultado final será el mismo al que obtenemos con la sintaxis vista anteriormente.
Queda en decisión del desarrollador utilizar una u otra sintaxis.

Resolveremos un ejercicio de conceptos anteriores pero ahora con la sintaxis propuesta con la clase FormBuilder.

Problema

Confeccionar un formulario de contacto que permita cargar el nombre, mail y un mensaje. Implementar las siguientes validaciones a los controles del formulario:

  • Los tres controles no pueden quedar vacíos.
  • El nombre debe tener como mínimo 10 caracteres.
  • El email ingresado debe ser correcto.
  • El mensaje no puede superar los 500 caracteres.

Cuando se presione un botón mostrar un mensaje indicando si todos los controles se encuentran correctamente cargados.

  • Crearemos primero el proyecto:

    ng new proyecto061
    
  • Importamos la clase 'ReactiveFormModule' modificando el archivo 'app.module.ts':

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { ReactiveFormsModule } from '@angular/forms';
    
    import { AppComponent } from './app.component';
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        ReactiveFormsModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    
    
  • Modificamos la vista de la componente que muestra el formulario reactivo y eventualmente los mensajes de error de entrada de datos (app.component.html):

    <form [formGroup]="formularioContacto" (ngSubmit)="submit()">
      <p>Nombre:
        <input type="text" formControlName="nombre" required>
        <span *ngIf="this.formularioContacto.get('nombre')?.errors?.['required']">
          (El nombre no puede quedar vacío)
        </span>
        <span *ngIf="this.formularioContacto.get('nombre')?.errors?.['minlength']">
          (Debe tener como mínimo 10 caracteres)
        </span>
      </p>
      <p>Mail:
        <input type="text" formControlName="mail">
        <span *ngIf="this.formularioContacto.get('mail')?.errors?.['required']">
          (El mail no puede quedar vacío)
        </span>
        <span *ngIf="this.formularioContacto.get('mail')?.errors?.['email']">
          (El mail no es válido)
        </span>
      </p>
      <p>Mensaje<br>
        <textarea rows="10" cols="70" formControlName="mensaje"></textarea>
      </p>
      <div *ngIf="this.formularioContacto.get('mensaje')?.errors?.['required']">
        (El mensaje no puede quedar vacío)
      </div>
      <div *ngIf="this.formularioContacto.get('mensaje')?.errors?.['maxlength']">
        (Debe tener como máximo 500 caracteres)
      </div>
      <button type="submit">Confirmar</button>
    </form>
    <div>{{resultado}}</div>
    

    Analizaremos este archivo en conjunto luego de presentar 'app.component.ts'

  • La clase asociada a la vista es (app.component.ts):

    import { Component } from '@angular/core';
    import { Validators, FormBuilder } from '@angular/forms';
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent {
      resultado!: string;
    
      constructor(private fb: FormBuilder) { }
    
      formularioContacto = this.fb.group({
        nombre: ['', [Validators.required, Validators.minLength(10)]],
        mail: ['', [Validators.required, Validators.email]],
        mensaje: ['', [Validators.required, Validators.maxLength(500)]]
      });
    
      submit() {
        if (this.formularioContacto.valid)
          this.resultado = "Todos los datos son válidos";
        else
          this.resultado = "Hay datos inválidos en el formulario";
      }
    
    }
    

    Lo primero que debemos hacer es importar la clase FormBuilder (ya no requerimos importar las clases FormGroup y FormControl):

    import { Validators, FormBuilder } from '@angular/forms';
    

    Se inyecta al constructor un objeto de la clase FormBuilder:

      constructor(private fb: FormBuilder) { }
    

    Llamamos al método 'group' de la clase FormBuilder y le pasamos un objeto literal indicando como atributos los nombres de los controles visuales definidos en HTML y como valor se le pasa un arreglo, cuyo primer elemento es el valor inicial del control y en el segundo elemento del arreglo pasamos otro arreglo con las funciones de validación que se le aplican a dicho campo:

      formularioContacto = this.fb.group({
        nombre: ['', [Validators.required, Validators.minLength(10)]],
        mail: ['', [Validators.required, Validators.email]],
        mensaje: ['', [Validators.required, Validators.maxLength(500)]]
      });
    

    Tener que el resultado es exactamente el mismo si utilizamos la sintaxis vista anteriormente:

      formularioContacto = new FormGroup({
        nombre: new FormControl('', [Validators.required, Validators.minLength(10)]),
        mail: new FormControl('', [Validators.required, Validators.email]),
        mensaje: new FormControl('', [Validators.required, Validators.maxLength(500)])
      });
    

Si ejecutamos la aplicación tenemos una interfaz similar a:

Formularios reactivos angular ReactiveFormsModule FormControl FormGroup validaciones Validators

Podemos probar esta aplicación en la web aquí.