Els formularis reactius en Angular proporcionen una manera més robusta i escalable de gestionar formularis complexos. A diferència dels formularis basats en plantilles, els formularis reactius es defineixen i gestionen completament en el codi TypeScript, oferint un major control i flexibilitat.

Contingut

Introducció als formularis reactius

Els formularis reactius es basen en un model de dades explícit i immutable, el que significa que cada canvi en el formulari crea un nou objecte de model. Això facilita la gestió de l'estat del formulari i la seva validació.

Avantatges dels formularis reactius

  • Control total: Tots els aspectes del formulari es defineixen en el codi TypeScript.
  • Validació avançada: És més fàcil implementar validacions complexes i personalitzades.
  • Escalabilitat: Ideal per a formularis grans i complexos.
  • Testabilitat: Els formularis reactius són més fàcils de provar unitàriament.

Configuració del mòdul de formularis reactius

Abans de començar a treballar amb formularis reactius, hem d'importar el mòdul ReactiveFormsModule en el nostre mòdul Angular.

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

@NgModule({
  imports: [
    // altres mòduls
    ReactiveFormsModule
  ],
  // altres configuracions
})
export class AppModule { }

Creació d'un formulari reactiu

Pas 1: Definir el formulari en el component TypeScript

Primer, hem de crear una instància de FormGroup i definir els controls del formulari utilitzant FormControl.

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

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

  constructor() {
    this.myForm = new FormGroup({
      name: new FormControl(''),
      email: new FormControl(''),
      password: new FormControl('')
    });
  }

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

Pas 2: Vincular el formulari en la plantilla HTML

Utilitzem la directiva formGroup per vincular el formulari definit en el component TypeScript amb la plantilla HTML.

<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
  <label for="name">Name:</label>
  <input id="name" formControlName="name">

  <label for="email">Email:</label>
  <input id="email" formControlName="email">

  <label for="password">Password:</label>
  <input id="password" type="password" formControlName="password">

  <button type="submit">Submit</button>
</form>

Validació de formularis reactius

Validació bàsica

Podem afegir validacions bàsiques utilitzant els validators integrats d'Angular.

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

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

Mostrar missatges d'error

Podem mostrar missatges d'error en la plantilla HTML basant-nos en l'estat de validació dels controls.

<div *ngIf="myForm.get('name').invalid && myForm.get('name').touched">
  <small *ngIf="myForm.get('name').errors.required">Name is required.</small>
</div>

<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 *ngIf="myForm.get('password').invalid && myForm.get('password').touched">
  <small *ngIf="myForm.get('password').errors.required">Password is required.</small>
  <small *ngIf="myForm.get('password').errors.minlength">Password must be at least 6 characters long.</small>
</div>

Exemple pràctic

Component TypeScript

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

@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]),
      email: new FormControl('', [Validators.required, Validators.email]),
      password: new FormControl('', [Validators.required, Validators.minLength(6)])
    });
  }

  onSubmit() {
    if (this.myForm.valid) {
      console.log(this.myForm.value);
    } else {
      console.log('Form is invalid');
    }
  }
}

Plantilla HTML

<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
  <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>
  </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>

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

  <button type="submit">Submit</button>
</form>

Exercicis pràctics

Exercici 1: Formulari de registre

Crea un formulari de registre amb els següents camps:

  • Nom d'usuari (obligatori)
  • Correu electrònic (obligatori i format d'email)
  • Contrasenya (obligatori i mínim 8 caràcters)
  • Confirmació de contrasenya (obligatori i ha de coincidir amb la contrasenya)

Solució

Component TypeScript

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

@Component({
  selector: 'app-register-form',
  templateUrl: './register-form.component.html'
})
export class RegisterFormComponent {
  registerForm: FormGroup;

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

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

  onSubmit() {
    if (this.registerForm.valid) {
      console.log(this.registerForm.value);
    } else {
      console.log('Form is invalid');
    }
  }
}

Plantilla HTML

<form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
  <label for="username">Username:</label>
  <input id="username" formControlName="username">
  <div *ngIf="registerForm.get('username').invalid && registerForm.get('username').touched">
    <small *ngIf="registerForm.get('username').errors.required">Username is required.</small>
  </div>

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

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

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

  <button type="submit">Register</button>
</form>

Conclusió

Els formularis reactius en Angular proporcionen una manera poderosa i flexible de gestionar formularis complexos. Amb un control total sobre l'estat del formulari i la seva validació, els formularis reactius són ideals per a aplicacions que requereixen una gestió avançada de formularis. Practicar amb exemples i exercicis és clau per dominar aquesta tècnica.

Curs d'Angular 2+

Mòdul 1: Introducció a Angular

Mòdul 2: Conceptes bàsics de TypeScript

Mòdul 3: Components i plantilles

Mòdul 4: Directives i pipes

Mòdul 5: Serveis i injecció de dependències

Mòdul 6: Enrutament i navegació

Mòdul 7: Formularis en Angular

Mòdul 8: Client HTTP i observables

Mòdul 9: Gestió d'estat

Mòdul 10: Proves en Angular

Mòdul 11: Temes avançats

Mòdul 12: Desplegament i millors pràctiques

© Copyright 2024. Tots els drets reservats