Angular v22

132 points by Klaster_1 a day ago on hackernews | 79 comments

Today, we are thrilled to announce the release of Angular v22. We continue to be proud of the work we do with each release. Our goal is to maintain a high quality stream of features and improvements that make the workflows for developers smooth no matter how they build Angular applications.

Angular is the solid foundation upon which you can build what’s next on the web. This release features updates across stability, ergonomics and more. We want Angular to be a sort of launch pad that you can use as you build your next great application.

There’s some great features to discuss, so let’s dive in.

Production Ready is the Name of the Game

On the Angular team, we take a lot of joy and pride in our ability to update our APIs to bring great new features to Angular. When bringing new features to the table, we typically release a feature as experimental or developer preview. This gives the team time to gather feedback and iterate on new features. During this time, features will undergo refinement with the intention of delivering the best possible version to the community. This is great except that it means some features will not be production ready even though developers are excited and ready to use them immediately. In this release, we’re excited to be bringing 3 significant Angular features to production-ready, stable status: Signal Forms, Angular Aria and the Asynchronous Reactivity APIs.

Signal Forms: Composable, Reactive and Ready to go

We designed Signal Forms to be the new, robust forms API. Signal forms combine the best parts of Reactive forms, the value of strongly typed forms, as well as the things developers love about template driven forms and reactivity of signals. We put all of that together to make a reactive, composable and declarative form solution. When we launched Signal Forms in v21, we received strong signals (pun intended) from teams inside and outside of Google that we were on the right track. Since then, we’ve updated Signal Forms by:

  • Adding a complete set of documentation with the updated guide on angular.dev.
  • Addressing a significant amount of feedback and issues submitted by the community.
  • Adding support for Angular Material and Angular Aria giving developers even more options with integrating forms.

Here’s an example of a form implementation 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 ready for production today, head over to the updated guide on angular.dev to get started.

Angular Aria: Accessible primitives to build apps for all users

The web was meant for everyone, regardless of how someone decides to interact with it: keyboard and mouse, screen-reader or some other method. Angular teams have needed a consistent, accessible yet customizable way to build components that enables them to build apps for all users. Angular Aria was a bold step in that direction when we released it in Angular v21. We wanted developers to bring the styles and business logic while the UI directives and patterns handled the accessibility. With that in mind, Angular Aria’s set of accessibility patterns is moving to production in Angular v22. Now, developers can ship their components using Angular Aria to users with confidence.

We’ve been busy preparing it for production, here are some of the updates we’ve made:

Angular Aria’s twelve UI patterns cover common accessibility patterns and are available to use in production now. Build apps all users can enjoy.

Press enter or click to view image in full size

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: a new frontier

At the community driven 2024 NgPoland conference, Angular team member Pawel Kozlowski shared his vision for how we could take the power of signals beyond the synchronous boundaries developers were used to. What came next was the team’s exploration into what would become a game changer for Angular developers: asynchronous signals with resource. The resource API carves a path for developers to leverage the non-blocking nature of asynchronous programming while maintaining the ergonomic niceties of the standard synchronous signal API.

/**
* 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...';
});

While resource provided a way for developers to request asynchronous resources we wanted to provide a practical application to demonstrate what was possible. As a result, httpResource was introduced as a way to fetch data over HTTP. This new approach made fetching data much more intuitive for developers with a simplified mental model.

/**
* 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 ready for production. As of Angular version 22, developers can now use both these APIs in their production apps with confidence knowing that they have been battle-tested and ready to serve your users.

For information on how to get with these powerful apis, visit the official guides on angular.dev.

Charting the Agentic Future

Angular is a great choice of platform for AI-native applications. Since the introduction of angular.dev/ai, we’ve been diligently working to expand our AI story in meaningful ways to meet developers at the frontlines of this new era of development. We believe this manifests in three critical ways:

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

The Angular team has made significant progress in both of these areas and we’re excited to share what we’ve been working on.

Agentic tooling for code authoring

As more and more developers use tools like Google’s Antigravity as their agent coding partners it is more important than ever that coding agents have the tools needed to effectively write modern Angular applications.

We’ve updated our Model Context Protocol (MCP) offering to include new tools for directly interacting with the development server while building applications.

devserver.wait_for_build allows agents to programmatically build the application and review the output for deciding next steps in the development process. For example, the build logs could reveal code errors that need to be revisited. A workflow like this enables self-healing loops for agents.

Press enter or click to view image in full size

Agentic environment asking for permission to use the devserver.wait_for_build MCP tool

Angular MCP also features tooling for starting and stopping the development server with devserver.start and devserver.stop, respectively. These tools create new agentic workflows to meet the needs of today’s developers.

These tools are all graduating to stable in this release along with the testing and end-to-end tools. Angular MCP features a growing list of tools to help you build modern Angular apps including the ai_tutor, modernize, onpush_zoneless_migration and more. To find out more about all the MCP tools available, check out angular.dev/ai/mcp.

Agent Skills for Angular

Building modern Angular apps with agents
As the framework evolves, keeping up with the growing API surface can be a challenge not just for developers, but also for AI coding assistants whose training data might not capture the latest patterns. To bridge this gap, we are introducing Angular Agent Skills, a standardized way to give AI agents immediate context and expertise on modern Angular development.

These are the first two developer-focused skills:

  • angular-developer: This core skill provides models with critical best practices and guidelines for writing modern Angular applications. It specifically covers cutting-edge features that standard models may lack deep training on, such as Angular Aria and Signal Forms. Agent skills use progressive disclosure. The file itself is less than 140 lines long, pulling in robust code samples and deep reference files only when the agent actually needs them.
  • angular-new-app: This skill is intended for those exploring Angular for the first time in an agentic environment. This skill guides your AI assistant through configuring a local environment ready for Angular coding.

These skills are available to use today in AI development tools like Antigravity or any environment where you run your agentic workflows.

Interested in seeing these tools in action? Check out our latest video on YouTube.

Skills to help contributors
Contributing to a major framework can be intimidating, so we’ve also rolled out a set of Contributor Skills.

These skills help explain the internal mental models required to develop features inside the Angular codebase itself. They are incredibly valuable for anyone looking to make their first pull request. We’ve found that even experienced team members discover value in reading through them to better understand the framework architecture.

Experimental WebMCP

Angular is excited to ship experimental support for WebMCP.

WebMCP represents an exciting new opportunity to shape the future of web interactions. It allows you to create and expose structured tools for agents to interact within the browser. Tools defined by an application allow AI assistants to interact with it directly, providing additional capabilities to the agent and reducing the need for DOM interactions.

These early iterations include support for defining tools for the entire app, routes, services. It also supports automatically generating tools from dynamic Signal Forms.

We’ve shipped docs to share more information about this new integration.

AI Development Platforms

The development community is experiencing an incredible boom in “builders”. These are people who want to bring their ideas to life with software but might not come from a traditional coding background. To support them, we’ve worked closely with the teams behind Google AI Studio and Gemini Canvas to ensure these builders can kick off their projects with the foundational strengths of Angular.

Prototype Directly in the Browser

You can use the built-in coding sandbox in the Gemini web app to create a full application directly in the browser.

For example, I recently used it to build an Angular app for my kid’s soccer team to track who is responsible for bringing snacks. By specifying “Angular” in the prompt, the generated app uses Angular. Once the code is generated, you can edit it manually in the browser, or just keep chatting with the AI to refine it. You can even expand its capabilities by simply asking it to integrate Firebase for backend storage and more.

Press enter or click to view image in full size

“Vibe Coding” in Google AI Studio

You can follow a similar workflow in Google AI Studio by selecting Angular from the configuration panel and start prompting.

Press enter or click to view image in full size

Here’s the app prompt:

“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.”

Press enter or click to view image in full size

Once the application generates an application a builder can continue to iterate, add features via chat, and eventually deploy it for the world to use. The barrier to entry for turning an idea into a structured Angular app has never been lower.

If you are building great apps you are welcomed in the Angular community no matter what.

API improvements

Angular’s vast API surface provides lots of value as is but we’re always working to improve it. Let’s explore some of the new features we’re bringing to developers everywhere in Angular v22.

Angular Router Enhancements

The Angular router is a solid, foundational piece of the story that makes Angular so compelling to developers all over the world. We’re excited to bring new features to the router to help ensure your applications meet your business needs.

Get Angular’s stories in your inbox

Join Medium for free to get updates from this writer.

Remember me for faster sign in

Here are a few of the updates you can enjoy in the latest release.

Integration with platform Navigation API

This update aligns the router with the native browser Navigation API, giving better control over user movement across applications with less boilerplate. Here is what that looks like in practice:

  • The Router can now intercept all navigation requests automatically. Works for RouterLink and standard anchor tags.
  • It leverages the browser’s native scroll behavior, ensuring users land exactly where they expect when navigating back and forth without requiring custom scroll-management logic all without any impact to bundle size.
  • It hooks directly into the browser’s native navigation lifecycle, making it much easier to trigger global loading indicators and broadcast accurate accessibility (a11y) announcements during page transitions.

Here’s how to enable access to this feature:

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

New controls for route cleanup

We are introducing two new features designed to give you more precise control over memory management by explicitly cleaning up unused resources. We are actively looking for feedback on these changes to determine if they should become the framework default in future releases.

  • withExperimentalAutoCleanupInjectors: This configuration tells the Router to automatically destroy the dependency injectors associated with routes that are no longer active. This prevents memory leaks by ensuring idle route-level providers and resources are properly disposed of when a user navigates away.
  • destroyDetachedRouteHandle: If you use a custom RouteReuseStrategy, disposing of cached routes historically required workarounds (like casting the opaque handle to any to manually call componentRef.destroy()). This new utility function provides an official, public API to cleanly destroy the component stored within a detached route handle.

We’d love your feedback on withExperimentalAutoCleanupInjectors as we could make it the default behavior if the community finds it to be a favorable addition.

Here’s how to get started:

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

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

The new @Service decorator

This release sees the introduction of a new decorator aimed at improving code readability and intention — @Service. Use this new decorator as a replacement of the @Injectable({ providedIn: ‘root' }) pattern for most use cases. In the event that your application use case requires deeper configuration or constructor injection, @Injectablewill still be available. We see this as a more intuitive way to define global singletons in your application.

Check out this new syntax in action:

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 is here

Sometimes applications feature large dependencies that are best loaded on demand, when needed. While Angular has supported lazy loading of components and routes, services have not been eligible for this same optimization. That all changes with the introduction of injectAsync. This new API supports asynchronous dependency injection, enabling code splitting. Support for asynchronous on-demand loading also means that applications can enjoy performance improvement.

The service must be auto-provided. Using the new @Service decorator handles this for you.

Here’s a code sample to help get 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 example, the ReportExporter service is not loaded until it is first used. Dependencies can also be prefetched, too.

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

The team is excited to see how developers can leverage this new feature to bring better performance to their applications. To learn more, head over to the official documentation for injectAsync on angular.dev.

If you are building great apps you are welcomed in the Angular community no matter what.

Other Improvements

This release is packed with even more API-related features, including:

  • TypeScript 6 Support: Stay on the cutting edge of the language with full compatibility.
  • Performance Enhancements: Continuous improvements to the template pipeline and runtime efficiency.

Angular templates are better than ever

This release has quite a few quality of life improvements designed to make authoring Angular templates better than before.

Comments are now supported in HTML elements

Code documentation serves as a vital tool for both developers and coding agents, allowing them to clarify the intent behind code or flag work that is in progress or planned for the future. To expand these documentation capabilities, we have introduced support at the element level, offering new ways to document code specifically at the property and binding level.

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

With this change you can now comment properties and bindings in templates for increased readability and clarity. As a plus, VS Code comment toggling is also supported.

Host Directive de-duplification

Angular now automatically de-duplicates host directives that match multiple times on the same element. To ensure clear resolution, if a directive matches both through the template and as a host directive, the template match “wins.” We’ve also streamlined the experience by merging the input and output maps of host directives. Finally, to maintain a clean API, Angular will now throw an error if an input or output is exposed under multiple names, preventing potential naming conflicts.

Spread syntax available in templates

Your templates are more expressive with support for spread and rest syntax. This update works with object literals, array liberals and function calls.

Here’s an example based on a component used in a coffee shop style 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 robust and less boilerplate with @switch

Developers can enjoy less verbose templates with multiple case matching in @switch statements. In the following example, two of the cases can share the same output, reducing unnecessary 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 helpful update to the @switch syntax is exhaustive checks for @switch blocks. With the introduction of exhaustive checks for @switch blocks, developers using union types will now receive compile-time errors if any potential values remain unhandled. To enable this check use 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>

Arrow Functions in Templates

Many developers have wanted to inline simple functions in templates but the template syntax restricted the ability to author functions directly in Angular templates. In the latest version of Angular, inline functions are valid in templates — with a few caveats.

  • Use arrow functions when authoring inline templates.
  • Keep functions short and simple — complex functions should not be called written in the template
<p>Stock: {{ item().stock }}</p>

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

As long as functions are not long running, it is fine to call a function in a template 🙂

Changes to changeDetection

We’ve made two important changes to the way developers specify details for change detection in components.

First, OnPush is now the default for new applications. This shift brings new applications in alignment with zoneless being the default for applications. This also, in turn, aligns well with Angular’s goal of performance by default. Now that it is the default, it also is no longer required to specify OnPushas a change detection strategy in components.

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

Second, the previous default, ChangeDetectionStrategy.Default is now called ChangeDetectionStrategy.Eager. This renaming helps developers who come across it reason with more clarity about what it does and how it impacts applications during change detection cycles.

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

A sneak peek at something new

Let’s shift gears and turn our attention toward everyone’s favorite topic: template errors. Template errors can be frustrating and difficult for developers and users. Developers try to develop defensive patterns in the component code while users may end up with a broken page. If that crash happens inside a high-stakes flow such as an e-commerce checkout, a single broken component can completely derail the user experience, bounce customers, and directly impact revenue. Angular is introducing a much-needed solution to improve this part of the application experience. Meet @boundary, a new API for implementing error boundaries directly within Angular templates.

Here’s an example of 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 critical or unpredictable code blocks in the new @boundary syntax, an isolated component failure will no longer take down the entire page. Errors are caught and developers can specify fallback content. It’s a significant win for both developer and user experience.

@boundary will be available as a developer preview in Q3 2026.

A note on deprecations

Webpack support, @angular-devkit/build-angular builders, @ngtools/webpack, etc. is deprecated in v22. We’re focusing on TSGo support in the application builder. We will be sharing more details in upcoming updates.

For more information on deprecations in this release, please review the Angular CHANGELOG.

A rock-solid foundation for the future

Angular v22 is more than just a collection of features; it is a commitment to the stability you rely on and the innovation you deserve. We can’t wait to see what you build on top of this foundation. Be sure to watch the official release event premiering June 5th 2026 at 9AM Pacific.

Get out there and build great apps.