angular-knowledge-patch
Angular Knowledge Patch (v19–v21)
Baseline: Angular through v18.x (signals basics, new control flow, standalone components, zoneless experimental, SSR hydration basics, esbuild builder).
This patch covers features from Angular v19 through v21 (2024-11 to 2025-11).
Index
| Topic | File | Key APIs |
|---|---|---|
| Signals & Reactivity | references/signals-and-reactivity.md | linkedSignal, resource, httpResource |
| Signal Forms | references/signal-forms.md | form(), FormField, validators |
| SSR & Hydration | references/ssr-and-hydration.md | RenderMode, ServerRoute, incremental hydration |
| Zoneless & Testing | references/zoneless-and-testing.md | provideZonelessChangeDetection, Vitest |
| Components & Templates | references/components-and-templates.md | Angular Aria, regex in templates, @defer viewport |
Quick Reference
Signal APIs at a glance
| API | Status | Import | Purpose |
|---|---|---|---|
linkedSignal |
Stable (v20) | @angular/core |
Writable signal that resets when source changes |
resource |
Experimental | @angular/core |
Signal-based async data loading |
httpResource |
Experimental | @angular/common/http |
Signal-based HTTP fetching (reads only) |
form() |
Experimental (v21+) | @angular/forms/signals |
Signal-based forms with schema validation |
linkedSignal — short form
const selected = linkedSignal(() => options()[0]);
selected.set(options()[2]); // writable
// Resets to options()[0] when options() changes
resource — basic pattern
import { resource, Signal } from '@angular/core';
const userId: Signal<string> = getUserId();
const userResource = resource({
params: () => ({ id: userId() }),
loader: ({ params, abortSignal }) =>
fetch(`/users/${params.id}`, { signal: abortSignal }),
});
// userResource.value(), .isLoading(), .error(), .hasValue()
// IMPORTANT: .value() throws in error state — guard with .hasValue()
httpResource — basic pattern
import { httpResource } from '@angular/common/http';
// Reactive URL — re-fetches when userId() changes
const user = httpResource<User>(() => `/api/user/${userId()}`);
// user.value(), .isLoading(), .error(), .hasValue(), .headers()
// Only for reads — use HttpClient directly for mutations
Zoneless Angular (stable v20.2, default v21)
bootstrapApplication(AppComponent, {
providers: [
provideZonelessChangeDetection(),
provideBrowserGlobalErrorListeners(),
],
});
// Remove zone.js polyfill from angular.json
Vitest (default in v21)
# Migrate existing Jasmine tests
ng g @schematics/angular:refactor-jasmine-vitest
Route-level render mode
import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRouteConfig: ServerRoute[] = [
{ path: '/login', mode: RenderMode.Server },
{ path: '/dashboard', mode: RenderMode.Client },
{
path: '/product/:id',
mode: RenderMode.Prerender,
async getPrerenderPaths() {
return (await inject(ProductService).getIds()).map((id) => ({ id }));
},
},
{ path: '/**', mode: RenderMode.Prerender },
];
Incremental hydration
provideClientHydration(withIncrementalHydration())
// Template
@defer (hydrate on viewport) {
<shopping-cart/>
}
Signal Forms — minimal example
import { form, FormField, required, email, submit } from '@angular/forms/signals';
loginModel = signal({ email: '', password: '' });
loginForm = form(this.loginModel, (schema) => {
required(schema.email, { message: 'Email is required' });
email(schema.email, { message: 'Invalid email' });
required(schema.password, { message: 'Password is required' });
});
Template: <input [formField]="loginForm.email" />, access state via loginForm.email() → .value(), .touched(), .valid(), .errors(), .dirty(), .pending().
linkedSignal — long form (preserve selection across source changes)
const selected = linkedSignal<ShippingMethod[], ShippingMethod>({
source: shippingOptions,
computation: (newOptions, previous) =>
newOptions.find(o => o.id === previous?.value.id) ?? newOptions[0],
});
httpResource — advanced request + Zod validation
const user = httpResource(() => ({
url: `/api/user/${userId()}`,
method: 'GET',
headers: { 'X-Special': 'true' },
params: { fast: 'yes' },
}));
// Response type variants
httpResource.text(() => url);
httpResource.blob(() => url);
// Zod validation
const res = httpResource(() => `/api/people/${id()}`, {
parse: starWarsPersonSchema.parse,
});
Angular Aria (developer preview, v21)
Headless accessible components: npm i @angular/aria. Patterns: Accordion, Combobox, Grid, Listbox, Menu, Tabs, Toolbar, Tree. Unstyled — you provide all CSS.
More from nevaberry/nevaberry-plugins
dioxus-knowledge-patch
Dioxus changes since training cutoff (latest: 0.7.4) — Signals replacing use_state, RSX macro overhaul, server functions, asset!() system, dx CLI, Element-as-Result. Load before working with Dioxus.
46rust-knowledge-patch
Rust changes since training cutoff (latest: 1.94.0) \u2014 Rust 2024 Edition, async closures, trait upcasting, new std APIs, cargo resolver v3. Load before working with Rust.
20postgresql-knowledge-patch
PostgreSQL changes since training cutoff (latest: 18.1) — JSON_TABLE, SQL/JSON functions, MERGE RETURNING, virtual generated columns, UUIDv7, temporal PRIMARY KEY. Load before working with PostgreSQL.
16bun-knowledge-patch
Bun changes since training cutoff (latest: 1.3.10) \u2014 S3 client, built-in SQL/Redis, route-based HTTP server, CSS bundler, V8 compatibility. Load before working with Bun.
14nextjs-knowledge-patch
Next.js changes since training cutoff (latest: 16.1) — proxy.ts, \"use cache\", Cache Components, navigation hooks, typed routes, auto PageProps, React 19.2. Load before working with Next.js.
14postgis-knowledge-patch
PostGIS changes since training cutoff (latest: 3.6.1) — SFCGAL CG_* rename, ST_CoverageClean, ST_AsRasterAgg, topology bigint IDs, viewport simplification, 3D SFCGAL ops. Load before working with PostGIS.
13