Angular PrimerAngular 22 · 2022 → 2026

Orientation — 2022 → 2026

What stayed the same, what changed, and the order to read this site in.

This page is the map. Read the five-point summary below, then jump to whichever topic you need. Every page that follows assumes only one thing: that you wrote Angular before, and that the framework you came back to is not the one you left.

What stayed the same

Almost all of it. Angular is still components with templates, dependency injection, services, routing and forms. ngOnInit still runs after the first render, [property] still binds one way and (event) the other, and *ngIf still works if you want it to. The mental model transfers.

What changed is how you write all of it. The framework stopped asking you to tell it when something changed, and started working it out from what you read.

The five changes that matter

If you only remember five things about Angular after 2022, these are the ones that change the code you write every day.

  1. Signals are how state is held. signal(), computed() and effect() replace most of the manual bookkeeping that used to go with BehaviorSubject and the async pipe. A template reads {{ count() }} and re-renders itself when count changes — no async pipe, no markForCheck(). Start with Signals.
  2. Zoneless is the default. There is no zone.js in a new project, and no patched browser APIs. Angular tracks what changed through signals and the template, not by monkey-patching setTimeout. See Zoneless change detection.
  3. Components are standalone. A normal app has no NgModule and no declarations array. A component imports exactly what its own template uses, which makes a component readable on its own. See Standalone components.
  4. The template language has real control flow. @if, @for and @switch are syntax now, not structural directives shipped in CommonModule. @for requires a track expression, and @defer can lazy-load a part of a page you may never scroll to. See Templates & control flow.
  5. Data loading is a signal too. resource() and httpResource() put loading, error and success states into one object you can read in a template, instead of a hand-rolled loading boolean and three subscriptions. See HTTP & async data.

The timeline, in one pass

You left somewhere around Angular 9–13. Here is what moved while you were gone, newest first:

  • v22 (current). @Service() for root-provided services, injectAsync() for lazy dependency loading, OnPush as the default change-detection strategy for new components, Signal Forms, resource and the ARIA APIs stable, WebMCP experimental. Template syntax gained spread and rest, inline arrow functions, multi-value @case, and exhaustive @switch checking via never.
  • v21. Zoneless became the default for new projects. provideCheckNoChangesConfig({ exhaustive: true }) for strict dev-mode checking.
  • v20. Angular's own build pipeline (esbuild/Vite) is the only one; HttpClient got withFetch() by default in new projects; SSR and hydration matured.
  • v19. standalone: true became the default and the flag started disappearing; @let in templates; incremental hydration landed as a developer preview.
  • v18. Zoneless change detection as an experimental provider, and the first usable @defer behaviour.
  • v17. The new control flow (@if/@for/@switch), deferrable views, and the new provideRouter-style standalone APIs.
  • v16. Signals arrived as a developer preview — the seed of everything above.
  • v15. Standalone components became stable, and the ng generate @angular/core:standalone migration became usable.
  • v14. Typed reactive forms and inject() outside of constructors, which is what made the standalone style possible at all.

Two of those are worth pausing on. Signals (v16) are the reason zoneless (v18–21) could happen, because the framework finally had a source of truth it could trust. And inject() (v14) is why the framework could stop leaning on constructors and NgModule provider arrays.

v22 in detail: the new things

Everything below is stable in v22 unless it says otherwise.

  • @Service() marks a class as a root-provided service in one line, replacing the @Injectable({ providedIn: 'root' }) incantation. autoProvided defaults to true. See Dependency injection.
  • injectAsync() awaits a dependency that arrives as a promise — a lazily loaded module, a WASM payload, a config file — inside an injection context.
  • OnPush by default. Components the CLI generates are change-detection-clean from the start. If you were hand-annotating every class in 2022, that job is done.
  • Signal Forms (@angular/forms/signals): form(), field-level validators, [formField], and a submit state you can read as a signal. See Forms.
  • resource() / httpResource() are stable and are the recommended way to load data.
  • Template syntax additions: spread/rest, inline arrow functions with inferred parameters, multiple values in a single @case, and an exhaustive @switch that fails the build when a never case is unhandled.
  • WebMCP (experimental): exposes an app's capabilities to browser agents over a standard protocol. Worth knowing about; not something to build on yet.

How this site is put together

The order below is the order the pages are meant to be read in, but nothing depends on reading them in sequence except the two you should not skip.

If you are here to fix something today, read Un-learn & upgrade first — it is a list of the patterns that are now actively wrong, with the error message each one produces. Then come back to the front.

The one-paragraph version

Angular is still the framework you know: components, templates, DI, routing, forms. It has stopped guessing when to re-render, and started knowing — because state lives in signals, and the template is honest about what it reads. Everything else on this site is a consequence of that single move.