What Is New in Angular 21
| Category | Highlights |
|---|---|
| New Features |
Signal Forms (experimental) -- reactive form API built on Signals; Angular ARIA -- headless accessibility component library (developer preview); Angular MCP Server -- AI-native CLI tooling via ng mcp;Typed SimpleChanges -- generic interface for type-safe ngOnChanges;Wildcard routes with trailing segments (21.1) -- e.g. foo/**/bar;Template spread/rest operator support (21.1); Multiple consecutive @case statements in @switch (21.1);Signal Forms Submission API (21.2); Signal Forms conditional CSS class support (21.2); TrailingSlashPathLocationStrategy / NoTrailingSlashPathLocationStrategy (21.2);height support in ImageLoaderConfig (21.2);AI runtime debugging tools registered in dev mode ( angular:di-graph);KeyValue pipe now supports objects with optional keys;New Material Design utility classes as alternative to CSS variables; CDK overlays now use native browser popovers |
| Improvements |
Zoneless change detection is now the default for new projects; Vitest replaces Karma as the default test runner (5--10x faster); onpush_zoneless_migration AI tool for automated migration planning;karma-to-vitest schematic for migrating existing projects;withExperimentalAutoCleanupInjectors() for router-provided service lifecycle (21.1);Angular Material and CDK receive zoneless compatibility improvements; provideNgReflectAttributes() available as an opt-in escape hatch in dev mode
|
| Breaking Changes |
Zone.js excluded from new project scaffolding by default;NgModuleFactory fully removed -- switch to dynamic import();Built-in HammerJS integration fully removed; ng-reflect-* DOM attributes no longer emitted by default;Node.js minimum v22.22.0 or v24.13.1; TypeScript minimum 5.9; Signal Forms: Field directive renamed to FormField / [field] binding removed
|
| Deprecations |
ChangeDetectionStrategy.Default deprecated in 21.2 in favor of explicit Eager or OnPush;RouterTestingModule deprecated in favor of RouterModule with provideLocationMocks()
|
What does zoneless change detection as the default mean for your Angular apps?
Zoneless change detection becoming the default in Angular 21 means that new projects no longer include Zone.js at all, and change detection is driven entirely by Signals rather than monkey-patched browser events. Zone.js has served Angular well for years, but it carried measurable weight in bundles and made debugging async boundaries harder than necessary. With Signals handling state propagation, Angular can render precisely and on-demand without Zone.js scanning the entire component tree after every event.
In practice, existing projects are not broken by this change. Your polyfills.ts continues to import Zone.js until you actively opt out. Zoneless reached a stable API milestone in Angular 20.2, so v21 simply promotes it to the default scaffolding posture.
Watch out for the migration path: your app is ready for zoneless if it already uses ChangeDetectionStrategy.OnPush broadly and drives state through Signals or the async pipe. Third-party libraries that depend on Zone.js patching will need verification before you cut the cord.
The Angular CLI's onpush_zoneless_migration MCP tool generates a component-by-component migration plan and flags risky dependencies -- cutting audit time from days to under an hour on most mid-size codebases.
// angular.json / application config -- opt in to zoneless manually for existing apps
import { provideZonelessChangeDetection } from '@angular/core';
export const appConfig: ApplicationConfig = {
providers: [
provideZonelessChangeDetection(),
// remove BrowserModule's Zone.js import from polyfills
]
};
How do Signal Forms in Angular 21 differ from Reactive Forms?
Signal Forms are a new experimental API available via @angular/forms/signals that replaces FormControl, FormGroup, and their RxJS-based subscriptions with a Signals-native model.
Form state -- values, validation results, touched status -- is exposed as Signals, so templates and components react through the same mechanism used everywhere else in a modern Angular app.
The most immediate benefit is eliminating the valueChanges.pipe(takeUntil(this.destroy$)) pattern that most Angular developers have written dozens of times. Reads are direct signal calls; you never subscribe, never unsubscribe, and Angular handles cleanup automatically.
// Before -- Reactive Forms
this.form.get('email').valueChanges
.pipe(takeUntil(this.destroy$))
.subscribe(value => this.handleChange(value));
// After -- Signal Forms (Angular 21+)
import { form, required, FormField } from '@angular/forms/signals';
readonly contactForm = form(signal({ email: '' }), (path) => {
required(path.email, { message: 'Email is required' });
});
// Read value anywhere
const emailValue = this.contactForm.fields.email.value();
This matters if your application has complex form interactions that currently rely on nested FormGroup chains and multiple subscription chains.
Signal Forms are still experimental, which means breaking changes can appear in patch releases. The Field directive was already renamed to FormField in the 21.0 patch cycle, and Angular 21.2 added the Submission API and conditional CSS class support. Plan to absorb further API changes before using Signal Forms in long-lived production code.
Why is Angular replacing Karma with Vitest, and how do you migrate?
Angular 21 makes Vitest the default test runner for new projects because Karma was deprecated in 2023 and has not kept pace with modern tooling expectations.
Vitest runs tests 5--10x faster than Karma in large workspaces, supports hot module replacement during test runs, and requires far less configuration -- no karma.conf.js, no Webpack test config.
For existing projects, run the official schematic to migrate automatically:
ng generate @angular/core:karma-to-vitest
The schematic handles standard configurations well. If your project uses a custom Webpack setup inside karma.conf.js, those sections must be rewritten for Vite manually -- there is no automated conversion for Webpack plugins.
Karma and Jasmine remain fully supported for teams that are not ready to migrate. Most teams find that the Vitest migration pays off quickly in CI time savings alone.
What is Angular ARIA and when should you add it to a project?
Angular ARIA is a new developer-preview library of headless, accessible UI components that ships with Angular 21. "Headless" means the library provides the correct ARIA roles, keyboard interactions, and focus management patterns -- but brings zero CSS -- so your design system keeps full visual control while Angular handles compliance.
The library covers common patterns like accordions, combo-boxes, tabs, and menus. This matters practically for teams shipping applications into EU markets, where the European Accessibility Act imposes legal obligations that manual ARIA implementations often miss. Adding the package is a single command:
ng add @angular/aria
Most teams should start by identifying the components where their current implementation has keyboard or ARIA gaps, adopt Angular ARIA selectively in those spots, and expand coverage incrementally. Replacing all custom UI at once is unnecessary and risky given the developer-preview status.
How does the Angular MCP Server change AI-assisted development workflows?
The Angular MCP Server, launched as part of Angular 21, exposes a Model Context Protocol interface that gives AI coding assistants -- including GitHub Copilot and Claude -- direct context about your project's component tree, services, and routing configuration. Instead of producing generic Angular boilerplate, the AI generates suggestions that match the actual patterns and current v21 APIs already in your codebase.
Start the MCP server from the CLI with:
ng mcp
The CLI also ships an interactive ai_tutor tool that launches an Angular learning assistant scoped to your specific project structure. Angular 21 also registers AI debugging tools in the browser during development, including angular:di-graph, which exposes the full dependency injection graph for in-page AI assistants.
Both tools run locally and only share code with cloud-based AI providers if you are using one -- local models stay fully offline.
In practice, the most immediately useful scenario is the onpush_zoneless_migration tool, which reads your codebase and produces a prioritized, component-level migration plan for the zoneless transition.
What breaking changes in Angular 21 require immediate attention before upgrading?
Several hard removals in Angular 21 will surface as build or runtime errors immediately after running ng update.
The most impactful ones are listed below -- address them in this order to minimize debugging time.
-
NgModuleFactory removed: Any direct usage of
NgModuleFactoryfor dynamic module loading throws a build error. MigrateloadChildrenstring syntax to:
RunloadChildren: () => import('./feature/feature.module').then(m => m.FeatureModule)ng updatefirst -- the schematic handles many cases automatically. Then grep for remainingNgModuleFactoryreferences. -
HammerJS integration removed:
HammerModuleimports throw errors. Replace swipe/pinch handlers with native Pointer Events or reinstall HammerJS and configure it manually outside Angular. -
ng-reflect-* attributes removed: Tests querying
[ng-reflect-name]selectors will fail silently. Replace them with explicitdata-testidattributes you control, or temporarily restore the old behavior withprovideNgReflectAttributes()in development mode while you migrate. -
Node.js minimum v22.22.0: The Angular CLI will not start on older Node versions. Update Node across dev machines, CI runners, and deployment targets before touching
package.json. -
TypeScript minimum 5.9: Run
npm install typescript@latestand address any new type errors before upgrading Angular. TypeScript 5.9 tightens inference on generic and conditional types, so errors it surfaces are usually real. -
ChangeDetectionStrategy.Default deprecated (21.2): The strategy is now named
Eager. No immediate runtime impact, but start replacingDefaultreferences to avoid warnings accumulating.
Frequently Asked Questions about Angular 21
Does upgrading to Angular 21 break existing apps that still use Zone.js?
No. Zone.js support is fully retained for existing applications. New projects generated with ng new exclude Zone.js by default, but any app that currently imports Zone.js in polyfills.ts continues to work unchanged until you actively opt out by calling provideZonelessChangeDetection() and removing the Zone.js import.
Can Signal Forms and Reactive Forms coexist in the same Angular 21 application?
Yes, both APIs work independently in the same project. You can import form from @angular/forms/signals for new form components while leaving existing FormGroup and FormControl instances untouched. This coexistence makes incremental adoption practical -- there is no requirement to migrate all forms at once.
How do I migrate from Karma to Vitest in an Angular 21 project?
Run ng generate @angular/core:karma-to-vitest and the schematic updates your angular.json, removes the Karma configuration, and installs the required Vitest dependencies. Standard setups complete without manual steps. Custom Webpack configurations inside karma.conf.js require manual rewriting because Vitest uses Vite, not Webpack.
What should I use instead of ng-reflect-* attributes in my tests after upgrading to Angular 21?
Add data-testid attributes directly to the template elements you want to query, then update your test selectors to use fixture.nativeElement.querySelector with the data-testid value. This approach is more stable than relying on framework-generated attributes and makes test intent explicit. The provideNgReflectAttributes() function restores the old behavior in development mode as a short-term bridge.
Is the Angular MCP Server safe to use with proprietary source code?
The MCP server runs locally and only transmits code to external AI providers if you are already using a cloud-based coding assistant such as GitHub Copilot or a remote Gemini instance. If you use a local AI model, no code leaves your machine. Review the data-sharing settings of your specific AI assistant before enabling the MCP server in repositories containing sensitive intellectual property.
What is ChangeDetectionStrategy.Eager in Angular 21 and how does it relate to Default?
Eager is a new, more descriptive name for what was previously called ChangeDetectionStrategy.Default. The Default alias was deprecated in Angular 21.2 and will be removed in a future major version. Functionally the two are identical -- the rename is purely semantic to make the strategy's behavior clearer compared to OnPush. Replace Default with Eager in your component decorators to stay ahead of the removal.