From knowledge-patch
Covers Angular 22.0.0 breaking changes (OnPush default, zoneless), signal forms, SSR, hydration, templates, testing, and tooling. Useful for writing, upgrading, and debugging Angular applications.
How this skill is triggered — by the user, by Claude, or both
Slash command
/knowledge-patch:angular-knowledge-patchThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use this skill when writing, reviewing, upgrading, or debugging modern Angular applications. Start with the breaking changes and defaults below, then open the topic reference that matches the task.
Use this skill when writing, reviewing, upgrading, or debugging modern Angular applications. Start with the breaking changes and defaults below, then open the topic reference that matches the task.
| Reference | Topics |
|---|---|
| Compatibility, security, and releases | Supported Node.js, TypeScript, and RxJS combinations; browser policy; support lifecycle; update hops; CSP and security changes |
| Core reactivity | Resources, effects, runtime bindings, zoneless change detection, services, signals, and core typing changes |
| Signal Forms | Field trees, schemas, validation, submission, custom controls, and Material/Aria integration |
| SSR, hydration, and routing | Hybrid rendering, server routes, incremental hydration, pending work, transfer cache, engines, and router lifecycle |
| Templates and animations | Template syntax, diagnostics, CSS enter/leave animation, defer triggers, and host-directive matching |
| Testing and tooling | Vitest, migrations, HMR, compiler checks, CLI tools, build changes, and removed test APIs |
| UI, platform, and DevTools | Angular Aria, Material, CDK, locale data, profiling, and debugging visualizations |
An omitted changeDetection now means OnPush. Use the renamed eager strategy only for a component that truly requires full eager checking:
@Component({
selector: 'legacy-widget',
template: `...`,
changeDetection: ChangeDetectionStrategy.Eager,
})
export class LegacyWidget {}
Audit code that mutates plain fields without a recognized notification. Prefer signals, markForCheck(), ComponentRef.setInput(), template/host listeners, or attachment of an already-dirty view.
Do not add ZoneJS as a reflex. Remove stale provideZoneChangeDetection() overrides, zone.js polyfills, and the package when migrating an application to the zoneless default. NgZone stability events do not report render timing under zoneless operation; use afterNextRender, afterEveryRender, or a DOM observer.
Reactive Forms mutations emit through form observables but do not themselves schedule a zoneless refresh. Bridge the relevant observable to a template-read signal or call markForCheck().
For server rendering, register application-owned asynchronous work with PendingTasks; router navigations and HttpClient calls are already registered.
Server route paths are slashless. Configure renderMode, and use getPrerenderParams for parameterized prerendering. Call inject() synchronously before any await in that callback.
export const serverRoutes: ServerRoute[] = [{
path: 'post/:id',
renderMode: RenderMode.Prerender,
fallback: PrerenderFallback.Client,
async getPrerenderParams() {
const posts = inject(PostService);
return (await posts.ids()).map(id => ({id}));
},
}];
The older mode and getPrerenderPaths names belong only to the preview contract. See the SSR reference before changing hybrid rendering or redirect behavior.
@ngtools/webpack are deprecated.TestBed.getFixture() is now TestBed.getLastFixture().ChangeDetectorRef.checkNoChanges() is removed; use fixture-level test APIs.Treat SVG animation URL attributes and object[data] as security-sensitive URL contexts. Translations cannot target iframe src; translated form attributes and translated interpolated bindings are sanitized. Do not bypass these checks to preserve old behavior.
Use resource for asynchronous reads driven by reactive parameters. Returning undefined from params leaves it idle; changing parameters aborts the previous load.
const user = resource({
params: () => id() ? {id: id()} : undefined,
loader: ({params, abortSignal}) =>
fetch(`/api/users/${params.id}`, {signal: abortSignal})
.then(response => response.json()),
});
Check hasValue() before value() because value() throws in the error state. reload() keeps the prior value with reloading status; set() and update() mark the value local.
Use:
httpResource for HttpClient-backed reads with interceptors, cancellation, testing support, response-type helpers, and optional parsing.rxResource when an Observable loader should publish each emission.stream when a resource source publishes a signal of {value} or {error} items.resourceFromSnapshots when transforming a resource's snapshot signal while preserving the resource interface.Keep mutation commands out of read resources. To submit explicitly, copy draft state into the signal used by params; reads performed only inside loader do not become reload dependencies.
Signal writes are allowed in effect; the old write opt-in is unnecessary. Root effects run before component checks and view effects run before their component is checked. Use afterRenderEffect for DOM- or query-dependent work.
afterRenderEffect({
earlyRead: () => host().nativeElement.getBoundingClientRect(),
write: rect => {
host().nativeElement.style.height = `${rect().width}px`;
},
});
Available phases are earlyRead, write, mixedReadWrite, and read; each later phase receives the prior phase result as a signal. The callback is client-only and can still run before its component hydrates.
Signal Forms turn a writable model signal into a callable typed field tree:
model = signal({email: '', password: ''});
loginForm = form(this.model, path => required(path.email));
<input [formField]="loginForm.email" />
Every bindable field must exist in the initial model. Prefer empty leaf values over absent optional properties or null object branches. Track array fields by field identity so their interaction and validation state survive reordering.
Schemas support built-in, custom, cross-field, HTTP, asynchronous, and Standard Schema validation, plus reactive disabled, hidden, and readonly rules. Read the forms reference before implementing arrays, submission, reset, custom controls, or validation timing.
For insertion and removal, attach classes with animate.enter and animate.leave instead of introducing the legacy animation DSL:
@if (shown()) {
<div animate.enter="enter" animate.leave="leave">Content</div>
}
Nested leave animations can run within the same component boundary.
@angular/aria provides unstyled directives for keyboard behavior, focus, ARIA state, screen-reader support, and RTL navigation. It covers autocomplete, listbox, select, multiselect, combobox, menu, menubar, toolbar, accordion, tabs, tree, and grid patterns. Keep markup, styling, and application behavior in the app.
createComponent and TestBed.createComponent accept inputBinding, outputBinding, and twoWayBinding. Runtime-applied directives can have their own binding lists. NgComponentOutlet can receive an EnvironmentInjector for an isolated provider scope.
Use @Service() as the concise root-singleton form when no deeper provider configuration or constructor injection is required. Such a service can be code-split with injectAsync and optionally prefetched on idle.
private exporter = injectAsync(() => import('./report-exporter'));
New projects use Vitest with a Node DOM emulator. ng test watches by default. Configure global Angular providers through a default-exported providersFile; use setupFiles for general initialization. Real-browser execution supports the Playwright or WebdriverIO Vitest providers.
Prefer await fixture.whenStable() in zoneless tests. Repeated unconditional fixture.detectChanges() can conceal missing change notifications; exhaustive no-change checks can expose them.
The CLI owns important portions of the Vitest configuration even when runnerConfig points to a custom file. Read the testing reference for target options, browser naming, migration limitations, and output files.
ng update, and ensure the destination is still supported.Preview APIs can change outside the normal deprecation guarantees. Confirm their current signatures before adopting them in long-lived libraries.
npx claudepluginhub nevaberry/nevaberry-plugins --plugin knowledge-patchProvides Angular v20+ patterns for components, signals, services, forms, routing, HTTP, SSR, testing, and tooling. Auto-activates on .ts files in Angular projects.
Guides modern Angular development (v20+) using Signals, Standalone Components, Zoneless apps, SSR/Hydration, and reactive patterns.
Delivers expert Angular v20 guidance covering Signals, Components, DI, Routing, Forms, HTTP Client, SSR/Hydration, Testing, i18n, Animations, and best practices. Activates on any Angular mention or file convention.