Angular 21 was a transition release: it made zoneless change detection the default, promoted Vitest to the primary unit-test runner, and introduced preview APIs for Signal Forms and Angular Aria. By September 2026, Angular 21 is in LTS and Angular 22 is active, so a current interview answer must explain both the original release and the stabilized follow-up.
This guide contains exactly 32 questions. It avoids treating every v21 preview as production-stable or claiming that Signals are Angular's only change-detection notification.
Table of Contents
- Angular 21 status and scope
- Signal Forms
- Zoneless change detection
- Vitest and testing
- Angular Aria
- Angular CLI MCP server
- Upgrade strategy
- Frequently asked questions
Angular 21 status and scope
1. What is the support status of Angular 21 in 2026?
Angular 21 was released on November 19, 2025. It entered long-term support when Angular 22 shipped on June 3, 2026 and is scheduled to receive critical and security fixes until June 2027. Angular 22 is the active release line in September 2026.
That distinction matters: LTS does not receive new framework features. A team that wants the stable forms and accessibility APIs described in current documentation should plan an upgrade rather than assume those changes were backported to v21.
2. What were Angular 21's headline changes?
The release is best remembered for four shifts:
- zoneless change detection became the default;
- the stable Vitest-based unit-test runner became primary for new CLI projects;
- Signal Forms launched as an experimental forms system;
- Angular Aria launched in developer preview as headless accessibility primitives.
The Angular CLI MCP server also expanded first-party support for AI-assisted workflows. Each item has a different stability and migration story; “introduced in v21” does not mean “automatically adopted by every upgraded application.”
3. What did Angular 22 change after Angular 21?
Angular 22 promoted Signal Forms and Angular Aria to stable. It also made OnPush the default change-detection strategy and renamed the previous Default strategy to Eager in the current API.
For interview preparation, describe v21 as the introduction/default transition and v22 as the stabilization step. Current examples should use v22 documentation rather than copy experimental v21 names such as Field and [field].
4. Does modern Angular no longer use RxJS or Reactive Forms?
No. Signals add a synchronous reactive primitive; they do not remove Observable streams, Reactive Forms or template-driven forms. RxJS remains useful for event streams, cancellation, composition and APIs that already expose Observables. Reactive Forms remain stable and are often the lower-risk choice for established or complex form codebases.
A strong answer chooses an abstraction based on state shape, event semantics, team experience, library integration and migration cost—not release marketing.
Signal Forms
5. What changed for Signal Forms after Angular 21?
Signal Forms debuted as experimental in Angular 21 and became stable in Angular 22. The stable API lives in @angular/forms/signals, imports the FormField directive and binds native or custom controls with [formField].
If an application must remain on Angular 21 LTS, Signal Forms are still an experimental v21 surface. Do not assume that the stable v22 contract or syntax is available unchanged there.
6. How do you create a stable Signal Form?
Create a writable signal as the source of truth, pass it to form(), then bind fields through FormField:
import { Component, signal } from '@angular/core';
import { email, form, FormField, required } from '@angular/forms/signals';
@Component({
selector: 'app-login',
imports: [FormField],
template: `
<form novalidate (submit)="submit($event)">
<input type="email" [formField]="loginForm.email" />
<input type="password" [formField]="loginForm.password" />
<button type="submit" [disabled]="!loginForm().valid()">Sign in</button>
</form>
`,
})
export class Login {
readonly model = signal({ email: '', password: '' });
readonly loginForm = form(this.model, (path) => {
required(path.email, { message: 'Email is required' });
email(path.email, { message: 'Enter a valid email' });
required(path.password, { message: 'Password is required' });
});
submit(event: SubmitEvent) {
event.preventDefault();
if (this.loginForm().invalid()) return;
// Send this.model() to a service after server-side validation is in place.
}
}Client validation improves UX but never replaces server validation, authorization or CSRF protection.
7. What is a FieldTree?
form(modelSignal) returns a FieldTree that mirrors the model shape. Both the root and nested nodes are callable; calling a node returns FieldState, whose properties such as value, valid, invalid, pending, errors, touched and dirty are signals.
The field tree is a typed view over form state, not a second independent domain model. Keep the domain model free of UI-only secrets and define an explicit transport mapping when the API contract differs.
8. How does [formField] synchronize a control?
The FormField directive connects a field-tree node to a compatible native or custom control. It synchronizes the control value with the model signal and reflects applicable state such as required, disabled and readonly.
Use native elements when they already provide the required semantics. Custom Signal Form controls implement the documented value-control contract and should expose accessible labels, focus behavior and errors; binding alone does not make a custom widget accessible.
9. How do you define Signal Forms validation?
Pass a schema function to form() and bind rules to paths. Synchronous validators run when interactive values change; asynchronous validation begins only after synchronous rules pass and is represented by pending().
import { form, minLength, required } from '@angular/forms/signals';
readonly accountForm = form(this.accountModel, (path) => {
required(path.username, { message: 'Username is required' });
minLength(path.password, 12, { message: 'Use at least 12 characters' });
});Do not infer “submittable” from !invalid() because valid() and invalid() can both be false while asynchronous validation is pending.
10. How do you write a custom Signal Forms validator?
validate() receives a field context. Read the current value from its signal and return an error object or null/undefined:
import { form, validate } from '@angular/forms/signals';
readonly profileForm = form(this.profileModel, (path) => {
validate(path.website, ({ value }) => {
const candidate = value();
if (candidate === '' || candidate.startsWith('https://')) return null;
return { kind: 'https', message: 'Use an HTTPS URL' };
});
});For external input, schema validation in the browser is still not a trust boundary. Repeat authoritative validation on the server.
11. How do touched, dirty, valid and pending differ?
touched()means an interactive field was focused and blurred or marked programmatically.dirty()means the user changed it, even if the value later equals the initial value.invalid()means validation errors exist.pending()means asynchronous validation is in progress.valid()means validation passed and no validator is pending.
Programmatic code uses markAsTouched(), not the old article's nonexistent markTouched(). Hidden, disabled and readonly fields are non-interactive and do not contribute to parent validity/touched/dirty state under the documented Signal Forms model.
12. When should you choose Signal Forms, Reactive Forms or template-driven forms?
Signal Forms fit new signal-based Angular 22+ applications that value inferred model types and schema validation. Reactive Forms are stable, Observable-based and often suit established, highly dynamic or integration-heavy forms. Template-driven forms remain useful for straightforward UI.
Avoid a big-bang rewrite. Angular 22 includes interoperability intended to support progressive migration. Measure maintenance cost, required controls, validation behavior and library compatibility before moving a mature forms platform.
Zoneless change detection
13. How does zoneless change detection work in Angular 21?
Zoneless is the default in Angular 21 and later. Instead of relying on Zone.js to patch asynchronous browser APIs and trigger application-wide checks, Angular schedules work from explicit framework notifications.
Signals are one source of notification, but not the only one. A component can remain zoneless-compatible through documented APIs even without converting every property to a signal.
14. Which APIs notify Angular in zoneless mode?
The official list includes:
- updating a signal read in a template;
ChangeDetectorRef.markForCheck()—also used byAsyncPipe;ComponentRef.setInput();- callbacks from bound template or host listeners;
- attaching a view already marked dirty by one of those mechanisms.
Audit code that relied only on “some async callback happened.” A plain property update inside an unbound timer or third-party callback needs an appropriate notification, such as updating a template-read signal or calling markForCheck().
15. Is OnPush required for zoneless Angular?
No. In Angular 21 it was a recommended way to expose notification mistakes, not a technical requirement. Components using the previous Default strategy could work when they notified Angular through signals, AsyncPipe, markForCheck() and other supported paths.
Angular 22 later made OnPush the default for newly compiled component behavior. Do not project that v22 default backward onto every v21 application or third-party library.
16. Why might a timer update fail to refresh the view?
A timer callback itself is not a zoneless notification. Make the relevant state reactive or notify Angular explicitly:
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-message',
template: `<p>{{ message() }}</p>`,
})
export class Message {
readonly message = signal('Waiting');
start() {
setTimeout(() => this.message.set('Finished'), 1000);
}
}The point is not “all state must be Signals.” The point is that Angular needs one of its known notifications when rendered state changes.
17. How do you enable or disable zoneless behavior?
Angular 21+ uses zoneless by default, so a new app needs no provider. Remove zone.js and zone.js/testing from build/test polyfills and uninstall the package after compatibility checks.
For a temporary fallback, install and load zone.js and configure provideZoneChangeDetection(). Angular 20 used provideZonelessChangeDetection() to opt in; carrying that migration-era snippet into a v21+ example is unnecessary.
18. What should a zoneless migration audit cover?
Look for:
- plain rendered state changed by unbound callbacks;
- direct DOM or third-party callbacks outside Angular notification paths;
NgZone.onMicrotaskEmpty,onUnstable,onStableandisStableassumptions;- template dependence on Reactive Forms state without
AsyncPipe, signals ormarkForCheck(); - libraries that expect Zone.js patches;
- tests that depend on
zone.js/testing,fakeAsyncor timing side effects.
Migrate in small slices, run component and browser tests, and observe real rendering—not just TypeScript compilation.
19. Do Signals guarantee that only one DOM node updates?
No. A template-read signal gives Angular a precise notification about a dependent view, but change detection, template evaluation and DOM writes are separate concepts. The strategy, component tree, bindings and compiler optimizations still matter.
Avoid unsupported bundle-size or speed guarantees. Profile a production build on representative devices and measure interaction latency, rendering work and memory before claiming an improvement.
Vitest and testing
20. Did Angular 21 remove Karma and Jasmine?
No. Angular 21 made the stable Vitest runner primary and the default for new CLI projects. Karma remains supported, and existing projects do not become Vitest suites merely by upgrading framework packages.
Treat the test runner, assertion library and DOM environment as separate decisions. Vitest normally uses jsdom or happy-dom in Node; browser mode with Playwright or WebdriverIO is available when real layout, browser APIs or engine behavior matter.
21. How do new Angular projects run Vitest?
The CLI configures the @angular/build:unit-test builder and installs Vitest plus a supported DOM emulation library. ng test builds the app and launches Vitest, normally in watch mode for an interactive terminal.
DOM emulation is not a browser-equivalence guarantee. Keep browser-level tests for focus behavior, rendering, CSS, navigation and integrations that depend on real browser engines.
22. How do you migrate an existing Karma suite?
First move to the application build system and configure the unit-test builder with Vitest and jsdom or happy-dom. Review custom launchers, reporters, assets, styles, polyfills and karma.conf.js; they are not translated automatically.
Then the experimental refactoring schematic can convert common Jasmine syntax:
ng generate @schematics/angular:refactor-jasmine-vitestIt does not install/configure every dependency, remove Karma files or understand every complex spy. Review the diff and run the complete suite before deleting the old setup.
23. How do Jasmine spies map to Vitest?
Common conversions include:
// Jasmine
spyOn(api, 'load').and.returnValue(result$);
// Vitest
vi.spyOn(api, 'load').mockReturnValue(result$);Reset or restore mocks in lifecycle hooks so state does not leak between tests. Prefer testing public behavior over reproducing implementation details with a large spy graph.
24. How should asynchronous Angular tests work with Vitest?
Prefer native async/await, fixture stability APIs and Vitest fake timers where time is part of the contract. Restore real timers after a test and avoid advancing all timers when only a specific boundary matters.
Angular offers zone.js/plugins/vitest-patch for compatibility with fakeAsync, flush and waitForAsync, but current guidance recommends planning a move toward native async and Vitest timers. A passing fake-timer unit test does not replace integration coverage for browser scheduling, network cancellation or server side effects.
Angular Aria
25. What is the current status of Angular Aria?
Angular Aria launched in developer preview in v21 and became stable in v22. It is a collection of headless directives implementing common WAI-ARIA interaction patterns, including keyboard navigation, ARIA attributes, focus management and screen-reader support.
“Headless” means the application supplies markup, styling and business logic. Stability does not turn every composition into an automatically accessible product.
26. Which patterns does Angular Aria cover?
Current documentation includes selection patterns such as autocomplete, listbox, select, multiselect and combobox; navigation/action patterns such as menu, menubar and toolbar; and content patterns such as accordion, tabs, tree and grid.
Import directives from their documented subpaths, such as @angular/aria/toolbar. Do not copy v21 preview selectors or counts into current code without checking the installed version's API reference.
27. When should you use Angular Aria, Material or native HTML?
Use native elements when they already express the interaction. Use Angular Material when a supported styled component matches the product. Use Angular Aria when a design system needs custom visuals but benefits from maintained interaction primitives.
In all cases, test names, roles, states, focus order, keyboard behavior, zoom, contrast and assistive-technology flows. A library is an implementation aid, not a WCAG conformance certificate.
Angular CLI MCP server
28. How do you run the Angular CLI MCP server?
Configure an MCP-capable host to launch:
npx @angular/cli mcpThe exact host configuration differs between editors and agents. Use --read-only to expose only non-mutating tools and --local-only to exclude tools that require internet access when those boundaries fit the task.
29. Which tools does the Angular MCP server expose?
The current default set includes ai_tutor, get_best_practices, list_projects, onpush_zoneless_migration, search_documentation, run_target, and dev-server start/stop/build-wait controls.
The old article's find_examples and modernize list is no longer the current documented default. Tool names evolve with CLI versions; inspect the server you actually run and pin the CLI when automation depends on a stable interface.
30. What are the security boundaries of AI-assisted Angular tooling?
MCP gives an agent structured capabilities; it does not guarantee correct code. Apply least privilege, prefer read-only mode for research, review generated diffs, restrict secrets, and require tests and human approval for deployments or destructive actions.
Documentation search can reduce hallucinated APIs, but project-specific architecture, accessibility, authorization and data-handling decisions still need evidence and ownership.
Upgrade strategy
31. How should a team upgrade from Angular 20 to 21 or 22?
Use the official Update Guide and ng update, moving one supported major at a time when required. Separate concerns:
- establish a clean baseline of builds, tests and production telemetry;
- update framework and CLI packages and apply reviewed migrations;
- verify SSR, hydration, libraries and browser support;
- migrate the test runner independently if desired;
- audit zoneless notifications before removing Zone.js;
- adopt Signal Forms or Angular Aria only where their current version and stability fit.
Since v21 is already LTS, a new migration in September 2026 should normally target active Angular 22 unless a dependency or support policy requires otherwise.
32. What migration mistakes should you mention in an interview?
Good examples include:
- combining framework, forms, testing and change-detection rewrites in one unreviewable release;
- assuming
ng updateproves runtime compatibility; - converting every Observable to a signal regardless of event semantics;
- believing zoneless requires Signals everywhere or OnPush everywhere in v21;
- deleting Zone.js before auditing third-party and test dependencies;
- treating an experimental schematic as a complete migration;
- copying preview Signal Forms/Aria APIs after v22 changed or stabilized them;
- using MCP output without permissions, review and verification.
A senior answer describes rollback boundaries, telemetry, staged exposure and the evidence required before each cleanup step.
Quick reference
| Capability | Angular 21 | Angular 22 / current status |
|---|---|---|
| Framework support | LTS through June 2027 | Active through June 2027 |
| Zoneless | Default and stable | Default; OnPush is also the default strategy |
| Signal Forms | Experimental | Stable; FormField / [formField] |
| Vitest runner | Stable and primary for new projects | Primary; Karma migration remains experimental |
| Angular Aria | Developer preview | Stable |
| CLI MCP | Available, evolving tools | Available; inspect current tool contract |
Frequently Asked Questions
What is the support status of Angular 21 in 2026?
Angular 21 was released on November 19, 2025 and entered LTS when Angular 22 shipped on June 3, 2026. It receives critical and security fixes until June 2027. Angular 22 is the active line, so interview answers should distinguish features introduced in v21 from APIs stabilized or changed in v22.
What changed for Signal Forms after Angular 21?
Signal Forms debuted as experimental in Angular 21 and became stable in Angular 22. Current stable syntax imports FormField from @angular/forms/signals and binds controls with [formField]. A project pinned to Angular 21 still uses an experimental API; upgrade to v22 before treating the current API as stable.
How does zoneless change detection work in Angular 21?
Zoneless is the default in Angular 21 and later. Angular schedules change detection from explicit notifications such as a template-read signal update, markForCheck or AsyncPipe, ComponentRef.setInput, a bound listener, or attaching a dirty view. Signals are important but not mandatory, and OnPush was recommended rather than required in v21.
Did Angular 21 remove Karma and Jasmine?
No. Angular 21 made the stable Vitest runner the default for new CLI projects, while Karma remained supported. Existing suites are not migrated automatically. The CLI's Jasmine-to-Vitest refactoring schematic is still experimental, requires the application build system, and must be followed by manual review and real test execution.
What is the current status of Angular Aria?
Angular Aria launched in developer preview with Angular 21 and became stable in Angular 22. It provides headless directives for common WAI-ARIA interaction patterns, including keyboard, focus and ARIA behavior. Teams still own semantic HTML, labels, styling, application logic and accessibility testing.
How do you run the Angular CLI MCP server?
Configure an MCP-capable host to run npx @angular/cli mcp. Current tools include documentation search, best practices, project discovery, dev-server controls, target execution, an AI tutor and OnPush-zoneless migration guidance. Tool availability changes with the CLI version, so query the installed server instead of hard-coding an old list.
Related articles
- Complete Frontend Developer Interview Guide
- Angular Change Detection Interview Guide
- Angular RxJS Interview Guide
Sources
- Angular versioning, release schedule and support
- Angular zoneless guide
- Signal Forms overview
- Signal Forms comparison
- Signal Forms validation
- Signal Forms field state
- Angular testing overview
- Migrating from Karma to Vitest
- Angular Aria overview
- Angular CLI MCP server
- Angular roadmap and feature status
