Skip to content

Commit 9d00836

Browse files
2025-11-angular21 (EN) (#33)
* 2025-11-angular21: DE * en * en * EN * EN * EN * EN * EN * typos
1 parent 2db830b commit 9d00836

File tree

2 files changed

+289
-0
lines changed

2 files changed

+289
-0
lines changed

blog/2025-11-angular21/README.md

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
---
2+
title: 'Angular 21 is here!'
3+
author: Angular Book Team
4+
5+
published: 2025-11-20
6+
lastModified: 2025-11-20
7+
keywords:
8+
- Angular
9+
- Angular 21
10+
- MCP-Server
11+
- ARIA
12+
- Zoneless
13+
- Signal Forms
14+
- Vitest
15+
- Karma
16+
language: en
17+
header: angular21.jpg
18+
sticky: true
19+
---
20+
21+
<!-- Before we dive into the usual end-of-year rush, there is news from the Angular world: -->
22+
On **November 19, 2025**, **Angular 21** was released!
23+
The most important updates: Signal Forms, zoneless apps, testing with Vitest, the new package `@angular/aria`, and more support for AI assistants.
24+
25+
As always, you can find the official release information in the [Angular Blog](https://blog.angular.dev/announcing-angular-v21-57946c34f14b).
26+
You can migrate an existing project to Angular 21 using the command `ng update`.
27+
Detailed information about the steps is available in the [Angular Update Guide](https://angular.dev/update-guide).
28+
29+
30+
## Versions of TypeScript and Node.js
31+
32+
The following versions of TypeScript and Node.js are required for Angular 21:
33+
34+
- TypeScript: >=5.9.0 <6.0.0
35+
- Node.js: ^20.19.0 || ^22.12.0 || ^24.0.0
36+
37+
You can find detailed information about supported versions in the [Angular documentation](https://angular.dev/reference/versions).
38+
39+
## Zoneless change detection: the new default
40+
41+
Angular has supported zoneless change detection for some time.
42+
In the past, the library Zone.js was used to detect changes to data.
43+
With signals as the new foundation, the approach has changed significantly: Signals explicitly announce when a value has changed.
44+
<!-- We covered this in detail in the [blog post about Angular 18](/blog/2024-05-angular18). -->
45+
46+
Now there is great news about this topic: Zoneless change detection is the new default!
47+
New applications created with Angular 21 use the new mechanism by default.
48+
When creating an application with `ng new`, we no longer need the `--zoneless` option.
49+
It is also no longer necessary to call the function `provideZonelessChangeDetection()` in `app.config.ts`.
50+
51+
If you still want to use the old Zone.js-based implementation for compatibility reasons, you can configure change detection in `app.config.ts`.
52+
Additionally, Zone.js must be installed and listed under `polyfills` in `angular.json` – just like it was in all applications in the past.
53+
54+
```ts
55+
export const appConfig: ApplicationConfig = {
56+
providers: [
57+
// ...
58+
// ENABLE the legacy change detection with Zone.js
59+
provideZoneChangeDetection({ eventCoalescing: true }),
60+
};
61+
```
62+
63+
64+
65+
## Signal Forms
66+
67+
The current approaches for form handling in Angular are not designed to work well with signals.
68+
Now a new experimental approach has been introduced: *Signal Forms*.
69+
This variant not only integrates signals extensively, but also aims to simplify how forms are created and managed.
70+
71+
The basic idea: The data lives inside a simple signal that we control.
72+
Angular derives the structure of the form from the data.
73+
The validation rules are defined as a schema, written directly in code.
74+
75+
```ts
76+
import { schema, form, Field } from '@angular/forms/signals';
77+
78+
export const bookFormSchema = schema<Book>(fieldPath => {
79+
required(fieldPath.isbn);
80+
minLength(fieldPath.isbn, 10);
81+
maxLength(fieldPath.isbn, 13);
82+
required(fieldPath.title);
83+
});
84+
85+
@Component({
86+
// ...
87+
imports: [Field]
88+
})
89+
export class MyForm {
90+
protected readonly bookData = signal<Book>({
91+
isbn: '',
92+
title: ''
93+
});
94+
95+
protected readonly bookForm = form(this.bookData, bookFormSchema);
96+
}
97+
```
98+
99+
In the template, we create the data bindings using a single directive:
100+
101+
```html
102+
<form>
103+
<input [field]="bookForm.isbn" />
104+
<input [field]="bookForm.title" />
105+
</form>
106+
```
107+
108+
We have published detailed blog posts on Signal Forms:
109+
110+
* [**Part 1: Getting Started with the Basics**](https://angular-buch.com/blog/2025-10-signal-forms-part1)
111+
* [**Part 2: Advanced Validation and Schema Patterns**](https://angular-buch.com/blog/2025-10-signal-forms-part2)
112+
* [**Part 3: Child Forms and Custom UI Controls**](https://angular-buch.com/blog/2025-10-signal-forms-part3)
113+
114+
In the long run, this new approach may replace the older variants *Reactive Forms* and *Template-Driven Forms*.
115+
The Angular team also places great emphasis on backward compatibility, so migrating to a signal-based form should not be a major problem.
116+
However, the new approach is still experimental, meaning that the interfaces and concepts are subject to change.
117+
118+
119+
## Vitest: the new test runner
120+
121+
Angular 21 brings one of the biggest changes in testing we've seen in years:
122+
[Vitest](https://vitest.dev) "officially" replaces Karma and Jasmine as the standard test runner.
123+
Vitest was already introduced as an experimental test runner in [Angular 20 (May 2025)](https://angular-buch.com/blog/2025-05-angular20#experimenteller-test-builder-f%C3%BCr-vitest).
124+
With Angular 21, Vitest is now officially stable and no longer marked as experimental.
125+
126+
Vitest then became the default for new projects with `ng new`.
127+
So for new projects, the path clearly leads to Vitest, but you can still choose Karma/Jasmine if you prefer:
128+
129+
```bash
130+
# Create a project with Vitest as the test runner
131+
ng new my-project
132+
133+
# Create a project with Karma as the test runner
134+
ng new my-project --test-runner=karma
135+
```
136+
137+
Vitest offers significant advantages: much faster test execution, modern APIs, a Jest-like expect syntax, flexible fake timers, and even a real browser mode if needed.
138+
The browser mode works similarly to how it did under Karma and is ideal for realistic UI tests.
139+
Most specs should continue to work unchanged, because Angular's `TestBed` and `ComponentFixture` remain exactly the same.
140+
The main changes are to Jasmine-specific matchers or spies.
141+
142+
The actual migration starts by using the new `unit-test` builder in `angular.json`.
143+
After that, you can use an experimental schematic for existing tests that automatically transfers many Jasmine patterns to Vitest:
144+
145+
```bash
146+
ng g @schematics/angular:refactor-jasmine-vitest
147+
```
148+
149+
At the same time, the Angular team has marked support for the test runners Jest and Web Test Runner as **deprecated**.
150+
We have put together a detailed migration guide, including practical examples for fake timers, matchers, and async/await:
151+
152+
* **[Vitest in Angular 21: What's new and how to migrate?](/blog/2025-11-migrate-to-vitest)**
153+
154+
155+
156+
## @angular/aria: accessible components made easy
157+
158+
With Angular 21, the new package [`@angular/aria`](https://angular.dev/guide/aria/overview) was introduced: a collection of directives that implement common [WAI-ARIA patterns](https://www.w3.org/WAI/ARIA/apg/patterns/).
159+
The package handles the complex work of accessibility, especially for more complex, frequently used patterns that go beyond standard HTML elements.
160+
Keyboard interactions, ARIA attributes, focus management, and screen reader support are all taken into account under the hood of the directives.
161+
162+
You install the new package as usual via the Angular CLI:
163+
164+
```bash
165+
ng add @angular/aria
166+
```
167+
168+
In its first version, `@angular/aria` provides directives for the following interactive patterns:
169+
170+
| Component | Description |
171+
| ---------------- | -------------------------------------------------------------------------------- |
172+
| **Accordion** | Expandable sections (accordion), which can be opened individually or exclusively |
173+
| **Autocomplete** | Text input with filtered suggestions while typing |
174+
| **Combobox** | Combination of text input and popup with search results |
175+
| **Grid** | Two-dimensional data display with cell-by-cell keyboard navigation |
176+
| **Listbox** | Single or multi-select option lists with keyboard navigation |
177+
| **Menu** | Dropdown menus with nested submenus and keyboard shortcuts |
178+
| **Multiselect** | Multi-select dropdown pattern with compact display |
179+
| **Select** | Single-select dropdown pattern with keyboard navigation |
180+
| **Tabs** | Tab interfaces with automatic or manual activation modes |
181+
| **Toolbar** | Grouped controls with logical keyboard navigation |
182+
| **Tree** | Hierarchical lists with expand/collapse functionality |
183+
184+
The new package is especially useful when developing complex components and when existing accessible component libraries cannot be used, for example because their styling cannot be adapted.
185+
The directives do not involve any visual elements, but ensure consistent behavior as well as barrier-free keyboard navigation, focus handling, and screen reader optimization.
186+
187+
You can find more information about the new directives in the Angular documentation: [Angular Aria Guide](https://angular.dev/guide/aria/overview)
188+
189+
> Some of these building blocks previously existed in similar form in the [Component Development Kit (CDK)](https://material.angular.dev/cdk/dialog/overview) of Angular. The CDK was the foundation of the Angular Material component library.
190+
> With `@angular/aria`, the Angular team brings the core of this collection closer to the Angular platform and strengthens the focus on accessibility.
191+
192+
193+
## Providers for `HttpClient`
194+
195+
With Angular 21, the providers for `HttpClient` are included automatically.
196+
This means it is no longer necessary to call the function `provideHttpClient()` in the file `app.config.ts`.
197+
198+
If we want to configure the HTTP integration, for example by adding interceptors or using the function `withFetch()`, we still need to call the function:
199+
200+
```ts
201+
// app.config.ts
202+
export const appConfig: ApplicationConfig = {
203+
providers: [
204+
// ...
205+
provideHttpClient(
206+
withFetch(),
207+
withInterceptors([ /* ... */ ])
208+
)
209+
]
210+
};
211+
```
212+
213+
## Angular's support for AI assistants
214+
215+
When creating a new application (`ng new`), the interactive prompt now asks whether you want to generate a config file for a specific AI tool (command-line option `--ai-config`).
216+
This creates a file that is automatically read as a _custom prompt_ by AI assistants such as Claude Code, GitHub Copilot, Cursor, and many others, supplying them with up-to-date Angular best practices:
217+
218+
```bash
219+
? Which AI tools do you want to configure with Angular best practices? https://angular.dev/ai/develop-with-ai
220+
None
221+
Agents.md [ https://agents.md/ ]
222+
❯◯ Claude [ https://docs.anthropic.com/en/docs/claude-code/memory ]
223+
Cursor [ https://docs.cursor.com/en/context/rules ]
224+
Gemini [ https://ai.google.dev/gemini-api/docs ]
225+
GitHub Copilot [ https://code.visualstudio.com/docs/copilot/copilot-customization ]
226+
JetBrains AI [ https://www.jetbrains.com/help/junie/customize-guidelines.html ]
227+
228+
↑↓ navigatespace selecta alli invert • ⏎ submit
229+
```
230+
231+
Depending on the selected tool, the file name and location differ, for example `.claude/CLAUDE.md` for Claude, `.gemini/GEMINI.md` for Gemini, or `AGENTS.md` following the [new standard](https://agents.md/), optionally with a frontmatter header.
232+
The actual content with Angular best practices remains identical.
233+
234+
There are, however, challenges: custom prompts are often forgotten during long sessions, and the limited context window can lead to inconsistent results.
235+
To address this issue, Angular additionally offers its own MCP server, which is now stable with Angular 21.
236+
The server gives AI agents structured access to seven tools.
237+
This closes the "knowledge gap" between the trained model and current best practices:
238+
LLMs can use brand-new features such as Signal Forms and Angular Aria, even though these did not exist at training time.
239+
240+
The MCP server currently provides seven tools:
241+
242+
1. Learn Angular with an interactive AI tutor (`ai_tutor`). See the documentation under ["Angular AI Tutor"](https://angular.dev/ai/ai-tutor).
243+
2. Find modern Angular pattern examples (`find_examples`).
244+
3. Provide best practices (`get_best_practices`).
245+
4. List all projects in the workspace (`list_projects`).
246+
5. Migrate the application to zoneless change detection (`onpush_zoneless_migration`).
247+
6. Search the documentation (`search_documentation`).
248+
7. Perform code migrations with schematics (`modernize`, **experimental**).
249+
250+
<!-- More details about `AGENTS.md`, MCP, and practical experience can be found in our detailed article about [Vibe Coding with Angular](/blog/2025-11-ai-mcp-vibe-coding). -->
251+
252+
253+
## Migration scripts
254+
255+
It is no longer recommended to use the `ngClass` directive.
256+
<!-- We already wrote about this one year ago [in a blog post](https://angular.schule/blog/2024-11-ngclass-ngstyle). -->
257+
To migrate to direct class bindings with `[class]`, Angular provides a migration script:
258+
259+
```bash
260+
ng generate @angular/core:ngclass-to-class
261+
```
262+
263+
The `RouterTestingModule` for unit tests is also no longer supported.
264+
A migration script can update the tests to the newer `provideRouterTesting()`, see the [commit](https://github.com/angular/angular/commit/861cee34e0e9b5562cfe70d245f30b7ddea7d8fd).
265+
266+
```bash
267+
ng generate @angular/core:router-testing-module-migration
268+
```
269+
270+
## Other updates
271+
272+
You can always find all the details about new features in the changelogs of [Angular](https://github.com/angular/angular/releases) and the [Angular CLI](https://github.com/angular/angular-cli/releases).
273+
We have collected some interesting highlights here:
274+
275+
* **Bindings for ARIA attributes:** Until now, we always had to use an attribute binding for ARIA attributes: `[attr.aria-label]="myLabel"`. These attributes can now be bound directly: `[aria-label]="myLabel"`.
276+
* **Regular expressions in templates:** Angular now supports regular expressions directly in templates (see [PR](https://github.com/angular/angular/pull/63857)).
277+
* **Tailwind support for `ng new`:** Angular has supported TailwindCSS for a while. Now the framework can also be configured directly when creating a new application: `ng new --style=tailwind` (see [commit](https://github.com/angular/angular-cli/commit/4912f39906b11a3212f11d5a00d577e2a0bacab4)).
278+
279+
<hr>
280+
281+
We wish you lots of fun developing with Angular 21!
282+
Do you have questions about the new version of Angular or about our book? Write to us!
283+
284+
**Have fun!
285+
Ferdinand, Danny and Johannes**
286+
287+
<hr>
288+
289+
<small>**Cover image:** Tre Cime di Lavaredo, Dolomites, Italy. Photo by Ferdinand Malcher</small>
611 KB
Loading

0 commit comments

Comments
 (0)