Publicado em

- 6 minutos de leitura

Angular 22: Novidades e Funcionalidades

img of 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 {}

Imagem com o texto: Curso Angular Moderno e um homem de pele parda usando óculos com a logo do Angular atrás. Logo abaixo existe um botão com o texto "Eu quero!"

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

Author's photo
Henrique Custódia Arquiteto Frontend, entusiasta Angular, cat lover, criador de conteúdo e fundador da Code Dimension!