Publicado em
- 6 minutos de leitura
Angular 22: Novidades e Funcionalidades
O lançamento do Angular 22 marca a consolidação definitiva da era “Signal-first”, transformando este poderoso framework de desenvolvimento web em uma ferramenta muito mais leve e voltada para a alta performance no frontend.
Esta versão foca em remover complexidades históricas, simplificando radicalmente a forma como escrevemos componentes usando Signal Forms, lidamos com chamadas de rede via Resource API e otimizamos a reatividade adotando o OnPush nativamente.
Abaixo, detalhamos cada uma das grandes novidades do Angular 22 que agora fazem parte da versão estável e como elas impactam o seu código.
1. Nova Função debounced() para Signals
O Angular 22 resolve um dos problemas mais comuns na web: aguardar o usuário parar de digitar antes de disparar uma ação.
A nova função debounced() recebe um Signal e um tempo de espera, retornando não apenas um valor, mas um Resource completo.
Isso significa que você tem acesso a propriedades como .value(), .isLoading() e .status() de forma nativa, sem precisar recorrer a conversores do RxJS ou a funções setTimeout manuais.
Veja como criar uma busca inteligente de forma simples:
import { Component, signal, debounced } from '@angular/core'
@Component({
selector: 'app-busca',
template: `
<input [value]="termo()" (input)="atualizar($event)" placeholder="Digite sua busca..." />
@if (termoAtrasado.isLoading()) {
<p>Aguardando digitação...</p>
} @else {
<p>Buscando por: {{ termoAtrasado.value() }}</p>
}
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class BuscaComponent {
termo = signal('')
termoAtrasado = debounced(() => this.termo(), 500)
atualizar(event: Event) {
const input = event.target as HTMLInputElement
this.termo.set(input.value)
}
}
2. Signal Forms está estável
O Signal Forms chega à sua versão estável trazendo uma mudança drástica de paradigma na construção de formulários no frontend.
Agora, a diretiva formRoot é aplicada diretamente na tag <form>, o que vincula a instância do seu Signal Form ao HTML e gerencia automaticamente eventos de submissão (como o clique no botão ou o Enter do teclado).
Além disso, a forma como definimos validações e submetemos os dados foi centralizada na declaração do formulário, deixando o código muito mais limpo e organizado.
Veja o exemplo de como usar o formRoot, as validações no schema e a nova API de submissão:
import { Component, signal } from '@angular/core'
import { form, FormField, FormRoot, required, email } from '@angular/forms/signals'
@Component({
selector: 'app-cadastro',
imports: [FormField, FormRoot],
template: `
<form [formRoot]="cadastroForm">
<input [formField]="cadastroForm.email" type="email" placeholder="Seu e-mail" />
@if (cadastroForm.email().touched()) {
@for (erro of cadastroForm.email().errors(); track erro) {
<span class="erro">{{ erro.message }}</span>
}
}
<button type="submit" [disabled]="cadastroForm().submitting() || cadastroForm().invalid()">
@if (cadastroForm().submitting()) {
Salvando...
} @else {
Salvar
}
</button>
</form>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CadastroComponent {
dados = signal({ email: '' })
cadastroForm = form(
this.dados,
(schema) => {
required(schema.email, { message: 'O e-mail é obrigatório!' })
email(schema.email, { message: 'Digite um e-mail válido.' })
},
{
submission: {
action: async (modelo) => {
try {
await new Promise((resolve) => setTimeout(resolve, 1000))
console.log('Sucesso:', modelo().value())
return null
} catch (error) {
return {
kind: 'FormError',
message: 'Erro ao salvar os dados.'
}
}
}
}
}
)
}
3. Resource API está estável também!
Por padrão, os Signals do Angular foram desenhados para serem puramente síncronos, o que sempre gerou desafios no desenvolvimento web ao lidar com APIs externas e processamentos demorados.
A grande revolução da Resource API é criar uma ponte nativa e elegante para operações assíncronas sem que você precise sair do ecossistema de Signals e entrar obrigatoriamente no RxJS.
Através de funções como resource() (para Promises) e rxResource() (para fluxos RxJS complexos), o Angular permite envelopar qualquer tarefa assíncrona dentro de um objeto reativo especial. Ele rastreia todo o ciclo de vida da operação, expondo o resultado final e o progresso em tempo real através de propriedades como .value(), .isLoading(), .error() e .status().
Além disso, ao usar um Signal dentro da propriedade request, a Resource API cancela requisições antigas e dispara uma nova execução de forma automática sempre que esse valor mudar, eliminando a necessidade de usar o operador switchMap do RxJS.
import { Component, signal, resource } from '@angular/core'
@Component({
selector: 'app-perfil-usuario',
template: `
<button (click)="proximoUsuario()">Próximo Usuário</button>
@if (usuario.isLoading()) {
<p>Carregando dados do servidor de forma assíncrona...</p>
} @else if (usuario.error()) {
<p>Erro encontrado: {{ usuario.error() }}</p>
} @else {
<h3>Nome: {{ usuario.value()?.name }}</h3>
}
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class PerfilUsuarioComponent {
usuarioId = signal(1)
usuario = resource({
params: () => ({ id: this.usuarioId() }),
loader: async ({ params }) => {
const res = await fetch(`https://api.exemplo.com/users/${params.id}`)
if (!res.ok) throw new Error('Falha na requisição')
return res.json()
}
})
proximoUsuario() {
this.usuarioId.update((id) => id + 1)
}
}
4. OnPush Strategy como Padrão
Entre as grandes novidades do Angular 22, a mudança para a estratégia ChangeDetectionStrategy.OnPush como padrão em todos os novos componentes é um marco histórico.
Essa mudança acontece porque o uso do Zone.js não é mais necessário nas aplicações modernas para garantir a reatividade da tela.
Antes dos Signals, o Zone.js precisava interceptar todos os eventos assíncronos da página para redesenhar o frontend inteiro de forma pouco otimizada, o que causava sérios gargalos de performance em aplicações com muitos dados.
Agora, graças à reatividade nativa dos Signals, o próprio framework sabe exatamente qual dado mudou e qual nó do DOM atualizar, tornando o monitoramento global do Zone.js completamente obsoleto.
Para evitar confusão nos projetos legados, o antigo comportamento de detecção de mudanças foi renomeado de Default para Eager.
// Componentes novos já nascem com OnPush nativo e livre de Zone.js.
@Component({
selector: 'app-antigo',
template: `<p>Modo de renderização constante com Zone.js</p>`,
// Se quiser usar o modo Eager antigo por compatibilidade, declare explicitamente:
changeDetection: ChangeDetectionStrategy.Eager
})
export class AntigoComponent {}
5. O Decorator @Service
O Angular 22 introduz o decorator @Service(), criado especificamente para simplificar a arquitetura de injeção de dependências no dia a dia do desenvolvimento web, substituindo o clássico @Injectable().
O @Injectable() é um decorator genérico que aceita diversas configurações complexas (como providedIn, useFactory, etc.), o que é excelente para autores de bibliotecas, mas gera ruído visual e complexidade desnecessária em aplicações comuns.
Ao usar o @Service(), o Angular assume automaticamente que aquele serviço deve ser um Singleton na raiz do projeto (exatamente como providedIn: 'root'), mas com uma sintaxe muito mais limpa.
Isso protege os desenvolvedores iniciantes de cometerem erros de escopo de injeção e impulsiona o uso da função inject().
import { Service, inject } from '@angular/core'
import { HttpClient } from '@angular/common/http'
@Service()
export class LogisticaService {
private http = inject(HttpClient)
rastrearEncomenda(codigo: string) {
return this.http.get(`/api/rastreio/${codigo}`)
}
}
6. TypeScript 6 Oficializado para o Desenvolvimento Web Angular
O suporte ao TypeScript 6 é mais uma das novidades do Angular 22, trazendo melhorias profundas de segurança e tipagem para o seu código.
Esta versão do compilador identifica erros potenciais mais cedo no seu editor de código, facilitando a vida do desenvolvedor frontend e evitando bugs em produção.
Além disso, ela prepara o terreno para otimizações futuras de compilação promovidas pela equipe do TypeScript.
7. Lazy-loading Otimizado com injectAsync()
A nova função injectAsync() no Angular 22 permite carregar arquivos de serviços de forma tardia, garantindo a alta performance do aplicativo.
Isso é perfeito para funções muito pesadas do frontend, como geradores de relatórios e exportadores, que não precisam travar o carregamento inicial da página do usuário.
import { Component } from '@angular/core'
@Component({
selector: 'app-fatura',
template: `<button (click)="exportar()">Baixar PDF</button>`
})
export class FaturaComponent {
async exportar() {
const pdfService = await injectAsync(() => import('./pdf.service').then((m) => m.PdfService))
pdfService.gerar()
}
}
Conclusão
O Angular 22 consolida a visão de um framework moderno de desenvolvimento web, onde a performance frontend e a simplicidade de código finalmente andam juntas.
A chegada da função debounced(), a evolução incrível do Signal Forms com a diretiva formRoot e as soluções assíncronas providas pela Resource API eliminam a obrigatoriedade de usar o RxJS para as tarefas comuns do dia a dia.
Com essas novidades, desde o OnPush ativado por padrão até o novo decorator @Service, a curva de aprendizado fica incrivelmente mais amigável. Migrar para o Angular 22 é um passo essencial para quem deseja extrair o máximo de velocidade de suas aplicações modernas, dando um adeus definitivo às limitações do Zone.js.
Entre na nossa comunidade!
Receba novos posts, novidades do ecossistema Angular e muito mais.
Sobre o autor