Aula 19 - Formulários Reativos Avançados e Validadores Customizados 📝
Objetivo Pedagógico
Objetivo: Construção de formulários complexos orientados a modelo com FormGroup, FormArray, tipagem estrita e validadores síncronos e assíncronos customizados.
📑 1. Fundamentos Teóricos & Análise Técnica
O módulo Reactive Forms do Angular adota uma abordagem estritamente funcional e orientada a dados para o gerenciamento de formulários. O estado e a validação do formulário são definidos de forma explícita na classe TypeScript através de classes como FormControl, FormGroup e FormArray, enquanto o template apenas se vincula declarativamente aos controles.
A partir do Angular 14+, os formulários reativos são estritamente tipados (Strictly Typed Forms), garantindo que o compilador verifique o tipo dos valores de cada campo em tempo de compilação, prevenindo erros em tempo de execução ao acessar propriedades inexistentes.
A validação de regras de negócio avançadas é realizada através de: 1. Validadores Síncronos: Funções puras que recebem um controle e retornam um mapa de erros (ValidationErrors | null) de forma síncrona. 2. Validadores Assíncronos: Funções que retornam uma Promise ou Observable emitindo o resultado após consultar um backend (ex: verificação de duplicidade de e-mail ou validação de CPF/CNPJ em serviço remoto). 3. FormArray Dinâmico: Permite adição e remoção programática de campos de entrada em tempo de execução (ex: lista dinâmica de telefones ou itens de fatura).
📐 Arquitetura Conceitual & Diagrama de Fluxo
graph LR
Model["FormGroup Tipado (TypeScript)"] --> Validators["Validadores (Sync / Async)"]
Model <--> Template["Template HTML ([formGroup])"]
Validators --> ValidationState["Estado (valid, invalid, dirty, touched)"]
ValidationState --> UI["Feedback Visual de Validação"]
style Model fill:#e3f2fd,stroke:#1565c0
style Validators fill:#fff3e0,stroke:#e65100
style UI fill:#e8f5e9,stroke:#2e7d32 🔍 Pilares e Diretrizes Técnicas
Nesta unidade, aprofundamos os seguintes conceitos fundamentais: - Formulários Estritamente Tipados: Garantia de tipos em tempo de compilação para form.value e métodos como patchValue. - Validadores Assíncronos Não-Bloqueantes: Consultas assíncronas que mantêm o status PENDING enquanto aguardam resposta de APIs. - Manipulação Dinâmica com FormArray: Coleções reativas de controles de formulário que crescem conforme a demanda do usuário. - Imutabilidade e Observabilidade: Acesso aos streams reativos de mudanças via valueChanges e statusChanges.
🛠️ 2. Implementação Prática em Angular Reactive Forms
Abaixo está a implementação técnica de referência, estruturada com padrões de engenharia de software e foco em robustez:
// user-form.component.ts (FormGroup Tipado com Validador Customizado)
import { Component, inject } from '@angular/core';
import { FormBuilder, Validators, ReactiveFormsModule, AbstractControl, ValidationErrors } from '@angular/forms';
import { CommonModule } from '@angular/common';
// Validador Customizado: Exige e-mail corporativo específico
export function corporateEmailValidator(control: AbstractControl): ValidationErrors | null {
const value = control.value as string;
if (!value) return null;
return value.endsWith('@empresa.com') ? null : { nonCorporateEmail: true };
}
@Component({
selector: 'app-user-form',
standalone: true,
imports: [CommonModule, ReactiveFormsModule],
template: `
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
<input formControlName="name" placeholder="Nome Completo">
<input formControlName="email" placeholder="E-mail Corporativo">
<span *ngIf="userForm.controls.email.errors?.['nonCorporateEmail']" class="error">
Deve ser um e-mail @empresa.com!
</span>
<button type="submit" [disabled]="userForm.invalid">Cadastrar</button>
</form>
`
})
export class UserFormComponent {
private readonly fb = inject(FormBuilder);
readonly userForm = this.fb.group({
name: ['', [Validators.required, Validators.minLength(3)]],
email: ['', [Validators.required, Validators.email, corporateEmailValidator]]
});
onSubmit(): void {
if (this.userForm.valid) {
console.log('Dados submetidos com sucesso:', this.userForm.value);
}
}
}
💡 Análise Passo a Passo do Código
- Validador Customizado:
corporateEmailValidatorinspeciona o valor e retorna um objeto de erro caso o domínio não seja aceito. - FormGroup Tipado:
fb.group()infere os tipos dos campos como strings não-nulas de acordo com os valores iniciais. - Feedback Declarativo: O template avalia
userForm.controls.email.errors?.['nonCorporateEmail']para exibir a mensagem corretiva.
🎯 3. Próximos Passos & Sequência Didática
-
Slides da Aula
-
Quiz de Fixação
-
Exercícios Práticos
-
Desafio de Projeto