DEV Community

Cover image for Angular v21 - Guia Prático de Migração e Como Dominar as Novas Signal Forms
Daniel Camucatto
Daniel Camucatto

Posted on

Angular v21 - Guia Prático de Migração e Como Dominar as Novas Signal Forms

O lançamento do Angular v21 não é apenas mais uma atualização; é um marco que redefine a forma como construímos aplicações. Esta versão solidifica o caminho para um Angular mais rápido, leve e, acima de tudo, mais intuitivo para o desenvolvedor.

Neste guia prático, vamos mergulhar nas duas grandes mudanças que impactarão diretamente o seu código:

  1. A revolução Zoneless (Sem zone.js por padrão), otimizando a performance.

  2. A aguardada introdução das Signal Forms, que prometem tornar a manipulação de formulários mais simples e reativa do que nunca.

Se você está pronto para migrar ou apenas quer aprender a usar a feature mais quente do momento, este é o seu guia.

1. O Fim do zone.js? Entendendo o Zoneless

Para quem trabalha com Angular há algum tempo, o zone.js era uma presença constante. Ele é a biblioteca responsável por interceptar eventos assíncronos (como clicks, requisições HTTP e setTimeout) para informar ao Angular quando rodar a Detecção de Mudanças.

Por que a Mudança no v21?

Com o amadurecimento dos Signals, a necessidade do zone.js diminuiu drasticamente. O v21 torna o modo Zoneless o padrão para novos projetos, o que traz benefícios imediatos:

  • Performance: Redução do bundle size (tamanho final do aplicativo) e menor overhead no runtime, resultando em Core Web Vitals (métricas de desempenho do Google) melhores.

  • Controle: Maior controle sobre quando as atualizações de UI devem acontecer, evitando ciclos de detecção de mudança desnecessários.

O que isso significa na prática?

Significa que o framework agora se baseia mais nos Signals para saber quais partes da interface precisam ser atualizadas, resultando em um código mais limpo e rápido.

2. Guia Prático: Migrando para o Angular v21

A migração para o v21 é crucial para acessar os benefícios de desempenho e as novas APIs.

Checklist de Atualização Rápida

  1. Pré-requisitos: Certifique-se de que o Node.js e o TypeScript estão nas versões mais recentes suportadas pelo Angular (sempre verifique o guia oficial de atualização para compatibilidade exata).

  2. Backup: Faça um commit ou um backup do seu projeto atual.

  3. Execução do ng update: Use o comando oficial do Angular CLI. Ele automatiza a maioria das mudanças nos arquivos de configuração e nos imports:

ng update @angular/cli @angular/core
Enter fullscreen mode Exit fullscreen mode
  1. Refatoração de NgZone (Se Necessário): Se o seu código dependia de injeção manual de NgZone ou de chamadas diretas para zone.run(), você precisará refatorar. Na maioria dos casos, o uso dos Signals ou de inject(ChangeDetectorRef).detectChanges() (para casos específicos) substituirá essa necessidade.

3. O Destaque: As Novas Signal Forms

Se você já se sentiu sobrecarregado(a) com a necessidade de usar RxJS e FormControl mesmo para os formulários mais simples, as Signal Forms são a resposta. Esta nova API está em fase experimental no v21, mas já é totalmente utilizável e vale o investimento.

Por Que Signal Forms?

No modelo antigo, os formulários reativos eram baseados em Observables. No Signal Forms, o estado do formulário (value, validity, status) é um Signal. Isso simplifica radicalmente o gerenciamento de estado e torna o código mais declarativo.

3.1. Criando Seu Primeiro Signal Form

Em vez de importar do '@angular/forms', importamos do @@angular/forms/signals' e usamos a nova função form() e field() do builder.

Exemplo de Componente (signal-cadastro.component.ts):

import { Component, inject } from '@angular/core';
// Importação dos Validators (Regras de Validação) ainda é a tradicional
import { Validators } from '@angular/forms'; 
// Importamos o FormBuilder específico para Signals
import { FormBuilder } from '@angular/forms/signals'; 

@Component({
  selector: 'app-signal-cadastro',
  standalone: true, // Idealmente em componentes standalone
  template: `
    <form [formGroup]="cadastroForm" (ngSubmit)="onSubmit()" class="p-6 bg-white shadow-xl rounded-lg">
      <h2 class="text-2xl font-bold mb-4">Cadastro de Usuário (v21)</h2>

      <!-- Campo de Usuário -->
      <div class="mb-4">
        <label for="usuario" class="block text-sm font-medium text-gray-700">Usuário:</label>
        <input id="usuario" type="text" formControlName="usuario" class="mt-1 block w-full p-2 border border-gray-300 rounded-md">

        <!-- Validação no Template (Detalhada na próxima seção) -->
        @if (cadastroForm.controls.usuario.errors() as errors) {
          <p class="text-red-600 text-xs mt-1">
            @if (errors['required']) { O nome de usuário é obrigatório. }
            @if (errors['minlength']) { Deve ter no mínimo 4 caracteres. }
          </p>
        }
      </div>

      <!-- Campo de Email -->
      <div class="mb-6">
        <label for="email" class="block text-sm font-medium text-gray-700">E-mail:</label>
        <input id="email" type="email" formControlName="email" class="mt-1 block w-full p-2 border border-gray-300 rounded-md">

        @if (cadastroForm.controls.email.errors() as errors) {
          <p class="text-red-600 text-xs mt-1">
            @if (errors['email']) { Digite um e-mail válido. }
          </p>
        }
      </div>

      <button type="submit" 
              [disabled]="cadastroForm.invalid()"
              class="w-full py-2 px-4 border border-transparent rounded-md text-white font-semibold bg-indigo-600 hover:bg-indigo-700 disabled:bg-indigo-300 transition duration-150">
        Cadastrar (Formulário Válido: {{ cadastroForm.valid() ? 'Sim' : 'Não' }})
      </button>
    </form>
  `,
  styles: `
    :host {
      display: flex;
      justify-content: center;
      padding: 2rem;
      background-color: #f3f4f6;
    }
    .shadow-xl {
      max-width: 400px;
      width: 100%;
    }
  `
})
export class SignalCadastroComponent {
  // 1. Injetamos o FormBuilder específico para Signals
  private fb = inject(FormBuilder);

  // 2. Definimos o formulário usando a função `form()`
  public cadastroForm = this.fb.form({
    usuario: this.fb.field('devuser', [Validators.required, Validators.minLength(4)]),
    email: this.fb.field('user@dev.to', Validators.email),
  });

  onSubmit() {
    if (this.cadastroForm.valid()) { 
      // Pegamos o valor do formulário chamando a função .value() do Signal
      console.log('Dados OK:', this.cadastroForm.value());
      alert('Cadastro Enviado com Sucesso!'); 
    } else {
      console.warn('Formulário inválido!');
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

3.2. Validação: Onde Brilha a Legibilidade

A maior melhoria é na manipulação de erros no template. Com os Control Flow do Angular (introduzido no v17) e os signals de erro do v21, o código se torna extremamente limpo:

  • Acesso ao Signal de Erros: Você acessa o objeto de erros através da função cadastroForm.controls.usuario.errors().

  • Reatividade Otimizada: O Angular só re-renderiza o bloco de erro quando o signal errors() muda (ou seja, quando o erro aparece ou desaparece).

<!-- Exemplo de como funciona a validação no Template -->
@if (cadastroForm.controls.usuario.errors() as errors) {
  <p class="text-red-600 text-xs mt-1">
    @if (errors['required']) {
      O nome de usuário é obrigatório.
    }
    @if (errors['minlength']) {
      Deve ter no mínimo 4 caracteres.
    }
  </p>
}
Enter fullscreen mode Exit fullscreen mode

Essa abordagem substitui a necessidade de encadear várias verificações de *ngIf e hasError(), tornando a manutenção do formulário muito mais simples.

4. Conclusão

O Angular v21 representa uma evolução significativa, tornando o desenvolvimento de formulários mais intuitivo e a aplicação mais rápida através da abordagem Zoneless e das Signal Forms. Este novo modelo é mais alinhado com o futuro reativo da web.

Sua vez de dominar o v21!

Você já migrou seu projeto? Qual é a feature do v21 que você está mais ansioso(a) para usar? Deixe sua experiência nos comentários!

Top comments (0)