What Is New in Angular v22
| Category | Highlights |
|---|---|
| New Features | @Service decorator, injectAsync for lazy-loaded services, @boundary error boundaries (developer preview), WebMCP experimental support, Arrow functions in templates, Spread syntax in templates, @switch multi-case matching and exhaustive checks, Router integration with browser Navigation API, withExperimentalAutoCleanupInjectors and destroyDetachedRouteHandle, HTML element-level comments in templates |
| Improvements | OnPush is now the default change detection strategy for new apps, ChangeDetectionStrategy.Default renamed to Eager, Angular MCP tools graduating to stable (devserver.start, devserver.stop, devserver.wait_for_build), Angular Agent Skills introduced, Host directive de-duplication, TypeScript 6 support, Template pipeline and runtime performance enhancements |
| Stable APIs | Signal Forms (was developer preview), Angular Aria (was developer preview), resource and httpResource async reactivity APIs (were developer preview) |
| Deprecations | Webpack support deprecated -- @angular-devkit/build-angular builders, @ngtools/webpack deprecated in favor of the application builder with TSGo support |
Are Signal Forms, Angular Aria, and resource APIs ready for production in Angular v22?
Yes -- Angular v22 promotes three major developer preview APIs to stable, production-ready status: Signal Forms, Angular Aria, and the async reactivity APIs (resource and httpResource).
This is the most consequential stabilization batch since signals themselves landed, and it represents a clean signal (pun intended) that the team has gathered enough real-world feedback to commit to these APIs long-term.
Signal Forms combine the type-safety of reactive forms with the ergonomics of template-driven forms, wired together with signals. The mental model is straightforward: you define your form state as a signal, call form() to create a typed form descriptor, and bind fields with [formField]. Validation lives in a schema callback, not scattered across validators and async validators.
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(this.paymentModel,
schema => {
required(schema.paymentType, { message: 'Required field' });
});
}
In practice, the f.paymentType().invalid() and f.paymentType().errors() APIs in the template are a significant ergonomic improvement over form.get('paymentType')?.errors. Touched, dirty, and error state are all signal-derived, so the template re-renders precisely.
Angular Aria ships twelve stable accessibility patterns -- tree, accordion, dialog, and more -- where you bring styles and business logic while the directives handle ARIA roles, keyboard navigation, and focus management. Test harnesses are included, which matters for teams with accessibility requirements in their CI pipeline. Signal Forms integration means your accessible form components get the full signal treatment out of the box.
resource and httpResource are the async signal primitives you have been waiting for. resource gives you a reactive container for any async operation keyed off signal params. httpResource wraps HTTP specifically, making the common case -- fetch data when a signal changes -- a one-liner. Watch out for: these replace a lot of toSignal(this.http.get(...)) patterns and you will want to migrate those once you are on v22.
export class WeatherComponent {
selectedCity = signal('Chicago');
weather = httpResource<{ temperature: number; condition: string }>(() =>
`https://api.example.com/v1/forecast/${this.selectedCity()}`
);
}
What new dependency injection features does Angular v22 introduce?
Angular v22 introduces two complementary DI additions that address long-standing gaps: the @Service decorator as a cleaner ergonomic default, and injectAsync for true lazy-loaded service code splitting.
@Service is a drop-in replacement for the verbose @Injectable({ providedIn: 'root' }) pattern that every Angular developer has typed thousands of times. For the overwhelming majority of services -- global singletons with no special configuration -- @Service() is all you need. @Injectable remains available for edge cases requiring constructor injection or fine-grained provider configuration.
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];
}
}
injectAsync is more impactful from a performance standpoint. Angular has supported lazy-loaded routes and components for years, but services were always eagerly bundled. With injectAsync, a service is not loaded until the first time it is actually called -- and because it uses dynamic import() under the hood, bundlers can split it into a separate chunk automatically.
@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();
}
}
This matters most for heavyweight services -- PDF generators, charting libraries, rich text editors -- that you do not want in the initial bundle. The optional prefetch: onIdle strategy gives you the best of both worlds: the service is not blocking the initial load, but it starts prefetching during idle time so it is likely warm before the user ever clicks.
What template authoring improvements shipped in Angular v22?
Angular v22 delivers a substantial batch of template quality-of-life improvements that collectively reduce boilerplate, improve expressiveness, and bring the template language closer to the TypeScript you already write.
Arrow functions are now valid in templates. The restriction on inline functions existed because of change detection concerns, but the Angular team has resolved those. The recommended pattern is concise update expressions -- keep business logic in the component class, use inline arrows for compact UI bindings:
<button (click)="item.update(p => ({ ...p, stock: p.stock - 1 }))">
Decrease Stock
</button>
Spread syntax lands in templates for object literals, array literals, and function calls. In practice this is most useful for dynamic class bindings and passing combined arrays to components without creating intermediate computed signals just for the template:
<div [class]="{ ...standardCupStyles, 'cardboard-sleeve': isHotDrink }"></div>
<app-bakery-cart [pastryOrder]="[...dailyPastryBasics, 'croissant', 'muffin']"/>
@switch gains multi-case matching and exhaustive checks. Multiple @case branches can now share an outcome without duplication. More importantly, @default never; enables compile-time exhaustiveness checking for union types -- if you add a new value to an order status union and forget to handle it in a switch, the template compiler will catch it:
@switch (orderStatus) {
@case ('Pending')
@case ('Processing') {
<p class="badge-blue">In progress</p>
}
@case ('Shipped') {
<p class="badge-green">On its way!</p>
}
@default never;
}
HTML element-level comments are now supported. You can now annotate individual attributes and bindings inside elements with // ... or /* ... */ comments. VS Code comment-toggling (Ctrl+/) works too. This is particularly valuable for documenting intent in complex host bindings and dynamic attribute expressions.
How does Angular v22 change default change detection and what does it mean for existing apps?
Angular v22 makes OnPush the default change detection strategy for new applications, and renames the old default (ChangeDetectionStrategy.Default) to ChangeDetectionStrategy.Eager.
This is a deliberate alignment with zoneless-by-default, which became the recommended configuration in recent releases. OnPush + zoneless is where the Angular team wants all new applications to land, and making it the default removes the friction of having to opt in. Components generated by the CLI will no longer carry the changeDetection: ChangeDetectionStrategy.OnPush annotation because it is redundant -- the default is now implied.
// New: OnPush is assumed, no annotation needed
@Component({
selector: 'app-weather',
template: `<section>Loading Weather...</section>`
})
export class WeatherComponent {}
// Old eager behavior is still available when you need it
@Component({
selector: 'app-legacy',
template: `<section>Legacy component</section>`,
changeDetection: ChangeDetectionStrategy.Eager
})
export class LegacyComponent {}
Watch out for: existing applications are not affected -- the defaults only apply to new apps generated with the CLI. If you are migrating an existing app toward zoneless, the Angular MCP tool onpush_zoneless_migration can automate most of the heavy lifting. The rename from Default to Eager is purely cosmetic but it is a better descriptor of what the strategy actually does: check everything, eagerly, on every CD cycle.
What agentic and AI development features does Angular v22 introduce?
Angular v22 makes a significant investment in agentic development tooling -- both for developers using AI coding assistants and for applications that want to expose structured tools to AI agents running in the browser.
Angular MCP tools graduate to stable. The Model Context Protocol server for Angular now includes devserver.start, devserver.stop, and devserver.wait_for_build. The last one is especially interesting for agent workflows: an agent can trigger a build, wait for completion, parse the compiler output for errors, and self-correct -- a proper self-healing loop without human intervention. Testing and end-to-end tools are also stable.
Angular Agent Skills are a new mechanism for giving AI coding assistants accurate, up-to-date context on modern Angular patterns. The angular-developer skill covers Signal Forms, Angular Aria, and other recently-stabilized APIs that may not be well-represented in an LLM's training data. The angular-new-app skill guides first-time setup. These are available at github.com/angular/skills and work in any MCP-compatible agent environment.
Experimental WebMCP is the most forward-looking addition. It lets Angular applications expose structured tools that AI agents running in the browser can call directly -- bypassing fragile DOM scraping. You can define tools at the app, route, and service level. Signal Forms get tools generated automatically. This is early (experimental), but it is the right primitive for building AI-native Angular apps where the AI interacts with the application through well-typed interfaces rather than simulated clicks.
Frequently Asked Questions -- Angular v22
Can I use Signal Forms in Angular v22 for production applications?
Yes -- Signal Forms are fully stable and production-ready in v22. The API has been hardened based on community feedback since its developer preview in v21, full documentation is available on angular.dev, and both Angular Material and Angular Aria integrations are supported.
Does the OnPush-by-default change in Angular v22 affect existing applications?
No -- the change only applies to new applications generated with the Angular CLI after upgrading to v22. Existing apps retain their current change detection configuration. If you want to migrate an existing app to OnPush and zoneless, the Angular MCP tool onpush_zoneless_migration can automate most of the migration for you.
How does injectAsync differ from lazy-loading a route in Angular?
Route-level lazy loading defers the entire component and its associated module, but the services those components depend on are still bundled eagerly. injectAsync operates at the service level: the service class itself is split into a separate chunk and not downloaded until the first time it is called. This is most valuable for heavyweight singleton services like PDF exporters or rich text editors that are only needed in specific user flows, keeping them out of the initial bundle entirely.
What is the @boundary template syntax and when will it be available?
The @boundary syntax introduces error boundaries directly into Angular templates, wrapping a component subtree so that runtime errors inside it are caught and replaced with fallback content rather than crashing the entire page. It uses @boundary to define the protected region and @error to specify the fallback. It ships as developer preview in Q3 2026 and is not yet available in the v22 stable release.
Is Webpack still supported in Angular v22?
Webpack support is deprecated in v22, including the @angular-devkit/build-angular builders and @ngtools/webpack. The team is focusing on TSGo support in the application builder. Deprecated does not mean removed immediately, but teams still on custom Webpack configurations should begin planning a migration to the Angular application builder.
What TypeScript version does Angular v22 require?
Angular v22 adds full support for TypeScript 6, keeping you on the cutting edge of the language. Earlier TypeScript versions supported in prior releases may still work but TypeScript 6 compatibility is the tested and recommended target for new v22 projects.