Announcing Angular v22

A vintage-style postcard graphic resting on a dark wooden table. The postcard reads “Welcome to” in yellow, cursive font across a sunset sky. Below the text, a large, rocky mountain features 3D white lettering that reads “Angular V22” alongside the Angular logo. The landscape is completed by evergreen trees surrounding the base of the mountain and birds flying in the background.

We are pleased to announce the release of Angular v22. The team remains dedicated to delivering a steady stream of high-quality features and refinements. Our focus is on providing a smooth developer experience, regardless of the size or type of application you are building with Angular.

Angular offers a dependable foundation for crafting the future of the web. This release brings enhancements centered on stability, usability, and API evolution. We view Angular as a launchpad to support you in creating your next outstanding application.

There is a lot to cover in this release, so let’s get started.

A Focus on Production Readiness

We take considerable care in evolving Angular's APIs. New features are often introduced in an experimental or developer preview state, which allows us to iterate and refine them based on community feedback before they are finalized. While this process is beneficial, it can mean that developers have to wait before they can use promising new features in production environments. With Angular v22, we are proud to promote three major features to a stable, production-ready status: Signal Forms, Angular Aria, and the Asynchronous Reactivity APIs.

Signal Forms: A Composable, Reactive Forms Solution

Signal Forms were created as the next-generation forms API for Angular. This API combines the best aspects of reactive forms, the safety of strong typing, the ease of template-driven forms, and the reactivity of signals into a single, declarative solution. Initial feedback from teams both within and outside Google following its preview release in v21 was very positive. Over the past year, we have enhanced Signal Forms by:

  • Creating a comprehensive set of documentation, including the updated guide on angular.dev.
  • Resolving a substantial number of issues and addressing community-provided feedback.
  • Introducing built-in support for Angular Material and Angular Aria, providing more integration options for developers.

Here's an example of a form with custom validation and template bindings:

/**
* Getting started with Signal Forms
**/
import {signal} from "@angular/core"
import {form} from "@angular/forms/signals"

@Component({
selector: 'app-payment',
imports: [FormField],
templateURL: './app-payment.html',
})
class Payment {
readonly paymentModel = signal({
paymentType: '',
amount: 0
});
readonly f = form(paymentModel,
schema => {
required(schema.paymentType, {
message: 'Required field'
});
});
}
<!-- app-payment.html -->
<form>
<section>
<label for="payment-type">Payment Type:</label>

<select id="payment-type" [formField]="f.paymentType">
<option value="">Select a method...</option>
<option value="credit">Credit Card</option>
<option value="paypal">Payment Service</option>
</select>

@if (f.paymentType().invalid() && f.paymentType().touched()) {
<p class="error">
@for (error of f.paymentType().errors(); track error.kind) {
<span>{{ error.message }}</span>
}
</p>
}
</section>

<button type="submit" [disabled]="f().invalid()">Submit Payment</button>
</form>

Signal Forms are now available for production use. To begin, visit the updated guide on angular.dev.

Angular Aria: Production-Ready Accessibility Primitives

The web is designed for all users, regardless of their input method—be it keyboard, mouse, or screen reader. There has been a need for a consistent, accessible, and flexible way to build components that serve everyone. Angular Aria, introduced in v21, was a step toward this goal, allowing developers to focus on their business logic and styles while delegating accessibility patterns to the framework. In Angular v22, the core set of Angular Aria patterns is now stable and production-ready.

Significant work has gone into preparing this for release:

Angular Aria's twelve UI patterns address common accessibility requirements and are ready for general use. Build applications that are enjoyable for all users.

A screenshot of a web browser displaying a file directory structure interface inside image_049485.png. The directory layout includes: public (an expanded folder) index.html (highlighted in purple with a checkmark next to it) favicon.ico styles.css src (a collapsed folder) angular.json (a standalone file) package.json (a standalone file) README.md (a standalone file)
Example Tree component using Angular Aria

Asynchronous Reactivity: Extending Signals

At NgPoland 2024, Angular team member Pawel Kozlowski presented a vision for extending signals beyond synchronous operations. This led to the creation of resource, an API that combines the power of asynchronous programming with the ergonomics of signals. The resource API allows developers to leverage non-blocking operations without sacrificing the familiar, synchronous signal developer experience.

/**
* Code example featuring weather forecasts using resource
*/
import { resource, signal, computed } from '@angular/core';

const selectedCity = signal('Chicago');

const weatherResource = resource({
params: () => ({ city: selectedCity() }),
loader: ({ params }) => fetchWeatherForecast(params.city),
});

const currentTemperature = computed(() => {
if (weatherResource.hasValue()) {
return `${weatherResource.value().temperature}°F`;
}
return 'Loading weather...';
});

To provide a concrete use case for resource, we also introduced httpResource. This API offers a straightforward way to fetch data over HTTP, simplifying the mental model and making it more intuitive for developers to manage data fetching.

/**
* This snippet demonstrates how httpResource enables declarative data fetching by
* automatically tracking the selectedCity signal.
*/
export class WeatherComponent {
selectedCity = signal('Chicago');

weather = httpResource<{ temperature: number; condition: string }>(() => {
return `https://api.example.com/v1/forecast/${this.selectedCity()}`;
});

changeCity(newCity: string) {
this.selectedCity.set(newCity);
}
}

Both resource and httpResource are now considered stable for production use. As of Angular v22, you can confidently use these APIs in your applications, knowing they have been thoroughly tested. For more details, please refer to the official guides on angular.dev.

Paving the Way for Agentic Development

Angular is an excellent platform for building AI-powered applications. Since the launch of angular.dev/ai, we have been expanding our AI-related tooling. We see our role in this new landscape in three key areas:

  • Agentic tooling for code authoring
  • Agentic browser tools
  • AI development platforms

We have made significant strides in these areas and are excited to share the results.

Agentic Code Authoring Tools

As developers increasingly rely on AI-powered coding partners like Google's Antigravity, it's crucial that these agents have the right capabilities to write effective Angular code. We have updated our Model Context Protocol (MCP) server to include new tools for interacting with the development server.

The devserver.wait_for_build tool allows an agent to wait for the application to build and then inspect the output. For example, build logs could reveal errors that need to be addressed, enabling a self-healing loop where the agent can correct its course.

The terminal text reads: Action Required ? devserver.wait_for_build (angular-cli MCP Server) {“project”:”fresh-angular-app”,”works… MCP Server: angular-cli Tool: devserver.wait_for_build MCP Tool Details: (press Ctrl+O to expand MCP tool details) Allow execution of MCP tool “devserver.wait_for_build” from server “angular-cli”? An interactive list of options is shown below the prompt, with the first option selected: 1. Allow once (highlighted with a green dot and background) Allow too
Agentic environment asking for permission to use the devserver.wait_for_build MCP tool

The MCP server also now includes tools for starting and stopping the dev server, devserver.start and devserver.stop, respectively. These new tools enable workflows that are more agentic than before. Along with the stable testing and end-to-end tools, Angular MCP provides a comprehensive suite, including ai_tutor, modernize, onpush_zoneless_migration, and more. For a full list, visit angular.dev/ai/mcp.

Angular Agent Skills

Building modern apps with the help of agents
The Angular API surface is constantly expanding, and staying current can be a challenge for both developers and AI models. To help AI assistants understand the latest best practices, we are introducing Angular Agent Skills. These provide AI agents with curated, up-to-date knowledge on modern Angular development.

We're launching with two core skills:

  • angular-developer: This foundational skill teaches AI models the key practices for writing modern Angular applications. It has a specific focus on newer features that models may have limited training data on, such as Angular Aria and Signal Forms. The skill uses progressive disclosure to remain efficient. The defining file is under 140 lines, with advanced code examples and detailed references loaded only when needed.
  • angular-new-app: This skill is for developers exploring Angular for the first time in an agentic environment. It guides your AI assistant through the setup of a local environment, making it ready for Angular development.

These skills are available now for use in AI development environments such as Antigravity or any other platform that supports agent workflows.

Want to see them in action? Watch our latest video for a demonstration.

Skills for contributors
We have also created a set of Contributor Skills to help those interested in contributing to the Angular project itself.

These skills clarify the internal architecture and mental models needed to develop features within the Angular codebase. While they provide a great starting point for new contributors, they can also serve as a valuable resource for more experienced team members looking to deepen their understanding of the framework's internals.

Introducing Experimental WebMCP

We are excited to ship experimental support for WebMCP.

WebMCP offers a new way to define how agents interact with your web application within the browser. It enables you to expose structured, custom tools for agents, which allows AI assistants to use those tools directly instead of relying on simulating clicks and typing. Applications can define tools at the app, route, or service level, and WebMCP can even automatically generate tools from dynamic Signal Forms in this initial implementation.

Please see the documentation for details on how to get started with this integration.

AI Development Platforms

There is a growing wave of "builders" who have ideas and want to create software, but who may not come from a traditional coding background. To support this community, we have worked with the teams at Google AI Studio and Gemini Canvas to ensure Angular is a top-tier choice for their projects.

Prototypage directly in the browser

The Gemini web application includes a coding sandbox, which you can use to build a full application directly in the browser. I recently used this feature to build a small app to manage snack duty for my kid's soccer team. By simply mentioning "Angular" in the prompt, the generated app was built with Angular. From there, you can edit the code directly in the browser or continue to refine it through conversation with the AI, for instance, by asking it to add Firebase for data persistence.

Screenshot of an AI web development workspace. The left chat panel shows a user’s request for a 3rd-grade math flashcard app and the AI’s step-by-step progress, detailing package installations and edits to 8 files like math.service.ts. The right panel previews the resulting app, “MATHMAGE,” featuring a modern purple-to-blue gradient interface. A central “KNOWLEDGE QUEST” flashcard displays the multiplication problem “12 × 9” under an “ARCANE TRAINING” label.

"Vibe Coding" in Google AI Studio

Google AI Studio offers a similar workflow. You can select Angular from the configuration panel and start creating your application.

A screenshot of the Google AI Studio interface with an “Advanced settings” sidebar open on the right. In the sidebar, the model configuration is set to “Default (Gemini 3 Flash Preview)”. Under the “Framework” dropdown menu, “Angular” is selected from options that include React and Next.js. The main workspace in the background is slightly blurred, displaying the text “Build your ideas with Gemini” above a prompt input box.

Here's the prompt I used:

"I need an Angular math facts app to help my 3rd grader improve multiplication skills. Make it use flash cards and keep track of progress on specific facts they struggle with."

A screenshot of a minimalist Google Gemini interface featuring the heading “Build your ideas with Gemini” next to a spark icon. A central prompt input box contains the text: “I need a math facts app to help my 3rd grader improve multiplication skills. Make it use flash cards and keep track of progress on specific facts they struggle with.” Below the box, chips offer options like “Convert text to speech,” “Generate music,” “Add database and auth,” and “Create & edit images.”

Once the app has been generated, builders can continue to iterate, add more features by chatting with the assistant, and can eventually deploy their project. The barrier to entry for taking an idea from concept to a structured Angular app has never been lower. If you're building great apps, you are a valued member of the Angular community, no matter your background.

API Enhancements

We are always working to refine Angular's vast API surface. Let's explore some of the new features in Angular v22's toolbox.

The Angular Router Gets New Capabilities

The Angular Router is a critical part of the platform. We're excited to add features to help ensure your applications can meet complex business requirements. Here's a sample of what's new in this release.

Integration with the platform Navigation API

This update gives the Router a closer alignment with the browser's native Navigation API, providing more control over in-app navigation with less code. Here are the practical benefits:

  • The Router can now intercept all navigation requests, including those from RouterLink and standard anchor tags.
  • It leverages the browser's native scroll behavior to manage scroll positions during back/forward navigation. This works without custom scroll management and without any impact on bundle size.
  • It ties into the native navigation lifecycle, simplifying the task of showing global loading indicators and making it easier to dispatch proper accessibility (a11y) announcements when a page transition occurs.

Here's how you can opt in to this feature:

bootstrapApplication(AppComponent, {
providers: [
provideRouter(appRoutes, withExperimentalPlatformNavigation())
]
});

New controls for route cleanup

We have introduced two new mechanisms to give you more explicit control over memory management by cleaning up unused resources. We are soliciting feedback on these to determine if they should be enabled by default in future releases.

  • withExperimentalAutoCleanupInjectors: This is a new Router feature that instructs the router to automatically destroy the dependency injectors associated with routes that are no longer being used. This helps prevent memory leaks by ensuring that route-level providers and resources are disposed of when you navigate away.
  • destroyDetachedRouteHandle: For those using a custom RouteReuseStrategy, disposing of a cached route previously required casting the opaque handle to any to manually call componentRef.destroy(). This new utility function offers an official, public API to properly destroy the component inside a detached route handle.

Please share your feedback on withExperimentalAutoCleanupInjectors, as it could become the framework's default behavior.

Here's an example of how to configure these options:

import { 
provideRouter,
withExperimentalAutoCleanupInjectors,
} from '@angular/router';

export const appConfig: ApplicationConfig = {
providers: [
provideRouter(
routes,
withExperimentalAutoCleanupInjectors(),
)
]
};

The new @Service decorator

We are introducing @Service, a new decorator to make your code more readable and expressive. This decorator is the recommended modern replacement for @Injectable({ providedIn: 'root' }) in most scenarios. @Injectable remains available for cases that require specific providedIn configurations or constructor injection. Think of @Service as the clear and intuitive way to define global singletons.

See how it works:

import {Service} from '@angular/core';

@Service()
export class BasicDataStore {
private data: string[] = [];
addData(item: string): void {
this.data.push(item);
}
getData(): string[] {
return [...this.data];
}
}

Asynchronous Dependency Injection

Some applications have large dependencies that are better loaded on demand. While Angular has long supported lazy loading for components and routes, this wasn't the case for services. injectAsync changes this by enabling asynchronous dependency injection. This opens the door to code-splitting for services, which can lead to significant performance improvements. The service you wish to load must be auto-provided; the new @Service decorator handles this automatically.

Here's an example to get you started:

import {Component, injectAsync} from '@angular/core';

@Component({
selector: 'app-report',
template: `<button (click)="export()">Export</button>`,
})
export class Report {
private exporter = injectAsync(() => import('./report-exporter'));
async export() {
const exporter = await this.exporter();
exporter.export();
}
}

In this snippet, the ReportExporter service is loaded lazily, only when it's needed for the first time. This same mechanism can also be used to prefetch dependencies.

export class Report {
private exporter = injectAsync(() => import('./report-exporter'), {
prefetch: onIdle,
});
}

We're looking forward to seeing how developers use this feature to build even more performant applications. For more details, visit the official documentation for injectAsync.

More Performance and Ecosystem Updates

The rest of the Angular platform continues to evolve as well. This release includes:

  • TypeScript 6 Support: Ensuring you have full compatibility with the latest version of TypeScript.
  • Performance Enhancements: Ongoing improvements to the template compiler and runtime for better efficiency.

Creating Better Angular Templates

This release contains several quality-of-life improvements that will make building Angular templates easier than ever.

Comments in Template Elements

Documentation is crucial for both developers and coding agents, as it clarifies the intent behind code and highlights work in progress. To expand your documentation options, Angular now supports comments at the element level. You can add comments to individual properties and bindings.

<div
// valid comment
/* another valid comment */
attr1="value1"
/*
a valid comment
spanning multiple
lines
*/
attr2="value2">
</div>

You can now comment on properties and bindings directly in your templates to improve readability and context. As an added benefit, this also works with the comment toggling feature in VS Code.

Host Directive De-duplication

Angular will now automatically de-duplicate host directives that are matched multiple times on the same element. To resolve conflicts, a directive matched directly in the template will take precedence over a host directive match. The maps of inputs and outputs for host directives have also been merged for a simpler experience. To avoid ambiguity, Angular will now throw an error if an input or output is exposed under multiple names.

Spread Syntax in Templates

Templates become more expressive with the introduction of spread and rest syntax. This feature is supported in object literals, array literals, and when making function calls. Here's an example from a coffee shop application:

<section>
<div [class]="{
...standardCupStyles,
'cardboard-sleeve': isHotDrink
}">
</div>

<app-bakery-cart [pastryOrder]="[...dailyPastryBasics, 'croissant', 'muffin']"/>

<p>
Total Cost: ${{ calculateBill(...baseItemPrices, salesTax, espressoShotPrice, syrupPrice) }}
</p>
</section>

More Expressive @switch Blocks

Writing templates becomes less verbose with the new support for matching multiple cases in a single @switch block. In the example below, two different cases can be grouped to share a single output, eliminating code duplication.

<section>
@switch (orderStatus) {
@case ('Pending')
@case ('Processing') {
<p class="badge-blue">In progress</p>
}
@case ('Shipped') {
<p class="badge-green">On its way!</p>
}
@default {
<p class="badge-gray">Unknown</p>
}
}
</section>

Another important addition is exhaustive checking for @switch blocks. When working with union types, Angular's compiler can now give you a compile-time error if not all potential values are handled by your cases. This is opt-in, and can be enabled by using the never value in the @default case:

<section>
@switch (orderStatus) {
@case ('Pending')
@case ('Processing') {
<p class="badge-blue">In Progress</p>
}
@case ('Shipped') {
<p class="badge-green">Shipped</p>
}
@default never;
}
</section>

Using Arrow Functions in Templates

A long-awaited feature has arrived: you can now define simple, inline functions directly in your templates. There are a few important guidelines to follow:

  • Only use arrow functions when writing inline template functions.
  • The functions should be short and simple. Complex, long-running logic should be placed in the component class.
<p>Stock: {{ item().stock }}</p>

<button
(click)="item.update(p => ({ ...p, stock: p.stock - 1 }))">
Decrease Stock
</button>

As long as the function executes quickly, it is perfectly fine to call it within a template.

Changes to Change Detection

We have made two notable adjustments to how change detection is configured.

First, OnPush is now the default strategy for new applications. This brings the change detection default in line with our other new defaults, like zoneless, and reinforces our commitment to performance. Since it's now the default, specifying OnPush in component decorators is no longer necessary.

// This component is using OnPush by default
@Component({
selector: 'app-weather',
template: `<section>Loading Weather...</section>`
})

Second, the prior default strategy, ChangeDetectionStrategy.Default, is being renamed to ChangeDetectionStrategy.Eager. This new name better reflects how the strategy works to reason about its effects on application performance.

@Component({
selector: 'app-weather',
template: `<section>Loading Weather...</section>`
changeDetection: ChangeDetectionStrategy.Eager
})

A Look Ahead: @boundary

Let's talk about one of our favorite topics: template errors. Template errors are a source of frustration for both developers and users. Developers have to write more defensive logic while users may end up with a broken page. A crash in a critical flow, like a checkout page, can derail the experience and cost you business. Angular is introducing @boundary to address this. It’s a new API for handling errors within Angular templates. Here's a look at the syntax:

<section>
<!-- Errors that bubble up through the promotional widget are caught -->
@boundary {
<app-promotional-widget />
}
@error (let err){
<!-- Fallback content -->
<app-default-promo-widget />
}
<app-cart-summary />
<app-checkout-flow />
</section>

By wrapping an unstable region of your template with @boundary, a single component can fail without taking down the whole page. Errors can be caught, and you can define a fallback UI to show in its place. This is a significant improvement for both the developer and user experience. @boundary will be available in developer preview starting in Q3 2026.

Deprecations to Note

As part of our continued investment in the application builder, we are deprecating Webpack support in v22. This includes features like @angular-devkit/build-angular builders and @ngtools/webpack. Further details will be shared in future updates. For a complete list of deprecations in this release, please review the Angular CHANGELOG.

A Solid Foundation for the Future

Angular v22 offers a mix of new features while solidifying the core that developers rely on. We look forward to seeing what you create. Be sure to watch the official release event premiering June 5th, 2026 at 9AM Pacific. Get out there and build great apps.


Announcing Angular v22 was originally published in Angular Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.