The questions you ask yourself ten times a day, with a short answer and a link to the page that explains it in depth. Search by a word or filter by category.
The principles behind every answer
- As close to use as possible
Types, components and state stay next to the code that uses them; you lift them only when a new consumer appears.
- One source of truth
What can be computed is derived (
computed), not stored. - The simplest tool that solves the problem
@switchbefore dynamic components, a signal-based service before NgRx, duplication before the wrong abstraction. - Immutability
New references for new data — signals and OnPush depend on it.
Questions and answers
41 of 41 questions
Components
7Is my component smart or dumb?
If it injects stores / APIs / the Router → smart (page or container). If it receives everything through inputs and emits outputs → dumb. Routed pages are smart; keep as many of the rest dumb as you can.
Smart vs DumbWhen do I make it generic (<T>)?
When you already have 2–3 uses with THE SAME behaviour on different data (table, select, list) and the API has no domain terms. Otherwise it stays specific.
Generic components <T>When do I make it dynamic?
Only when you don’t know at compile time which component appears (config, CMS, plugins, dashboard). For 2–5 known variants use @switch.
Dynamic componentsinput + output or model()?
model() for “control” values (toggle, slider, active tab). input + output when the parent must decide/validate, or the event has meaning (save, delete).
model() — two-way bindingng-content or ng-template?
ng-content for static content shown once. ng-template when the content must be created lazily, repeated, or receive data (context).
Content projectionComponent or directive?
Directive if you only add behaviour to an existing element (tooltip, autofocus). Component if you have your own markup or styles.
Directives & host compositionProjection or inputs for content?
Inputs when the component controls the look (consistency). Projection when the parent needs free markup (dialogs, cards).
Content projectionArchitecture
7Move the component to shared?
Only if it is used NOW in 2+ features, has no domain terms, doesn’t inject data and behaves the same everywhere. Otherwise it lives in features/x/ui.
Shared vs featureInline interface or separate file?
Used by a single file → inline. Input/output type → exported from the component file. Used by several files in a feature → features/x/models. Between features → the owner’s public API.
Interfaces & modelsDo I make a separate DTO from the model?
Yes, if the API uses other conventions, you don’t control it, or the UI has derived fields. No, for simple CRUD with types that are already clean.
Interfaces & modelsWhat goes in core?
Things used once at application level or as infrastructure: auth, layout (shell), ErrorHandler, interceptors, cross-cutting services.
Folder structureCan I import one feature from another?
Ideally not. Communicate through the URL, a store in core, or shared. If unavoidable: only through the other feature’s public API (index.ts).
Barrels, aliases & boundariesBarrel (index.ts) everywhere?
No. Only at the boundary of a feature/library, as its public API. Inside, import files directly.
Barrels, aliases & boundariesEnum or string union?
Union + as const object. Simpler, tree-shakable, easy to iterate in templates.
Interfaces & modelsState & data
7signal, computed or linkedSignal?
signal = independent state. computed = derived, read-only. linkedSignal = derived, but editable (a selection that resets, a draft of an input).
linkedSignal() — editable derived stateWhen do I use effect()?
Only for effects on the outside: localStorage, logging, imperative libraries, the DOM. Never to set another signal (→ computed / linkedSignal).
effect() — when YES, when NOSignal or Observable?
Signal for displayed state. Observable for event streams over time (websocket, drag, complex operators). The bridge: toSignal / toObservable.
Signals ↔ RxJSHow do I load data from the server?
Reactive reads → httpResource (or resource / rxResource). Writes (POST/PUT/DELETE) → HttpClient, then update/reload the resource.
resource, rxResource, httpResourceWhere do I keep state?
As low as possible: component → feature store (providers on the route/page) → global (@Service in root). Shareable filters → the URL.
State management with signalsDo I need NgRx?
Usually not: a service with signals is enough. NgRx SignalStore if you want conventions/plugins; NgRx Store if you need an action log and time-travel.
State management with signalsDebounce on a signal?
debounced(sig, 300) (v22, experimental). In Signal Forms: the debounce() rule or the debounce option of validateHttp.
debounced() — delayed signalsTemplate
5Method, pipe or computed in the template?
computed for calculations specific to the component; a pure pipe for reusable formatting; a method only for trivial things (it runs on every render).
Pipes: when and howWhat do I track in @for?
A stable id (track item.id). $index only for static lists. Identity (track item) only if the objects are not recreated.
Control flow: @if, @for, @switchngClass or [class]?
[class.x] / [class] — native, no import, faster. Migration: ng g @angular/core:ngclass-to-class.
Class & style bindingsWhen @defer?
Heavy content or content below the fold (charts, comments, editors). Not for the main content (LCP).
@defer — lazy loading in templatesHow much logic in the template?
Simple expressions and @let for sub-expressions. Business rules and calculations on large lists → computed.
@let and the new template expressionsDI
5@Service() or @Injectable()?
New code in v22: @Service() (auto-provided singleton, inject() only). @Injectable if you use constructor DI or need support for older versions.
inject() & @Service()Where do I provide the service?
Root if the state must survive navigation. Route/page for feature state. Component for one instance per component (wizard, editor).
Providers & the injector hierarchyClass or InjectionToken?
Class when you have logic/methods. InjectionToken for values: config, URLs, functions, plugins (multi).
InjectionToken & provideX()An interface for the service (IUserService)?
No. If you need several implementations or mocks: an abstract class as the token, with @Service({ factory }) for the default implementation.
inject() & @Service()Heavy service, rarely used?
injectAsync(() => import(...)) with prefetch: onIdle (v22).
injectAsync() — lazy servicesForms & routing
6Signal Forms or Reactive Forms?
New forms in v22 → Signal Forms. Existing Reactive ones stay; you migrate gradually with SignalFormControl / compatForm.
Signal Forms — the basicsCustom control: FormValueControl or CVA?
FormValueControl for Signal Forms (a model() + optional inputs). ControlValueAccessor for Reactive / template-driven.
Custom form controlsResolver or httpResource?
Resolver for small, required data. httpResource + skeleton for lists and dashboards (instant navigation).
Guards & resolverscanMatch or canActivate?
canMatch for restricted areas (it doesn’t download the chunk). canActivate for checks on entering a route that exists for everyone.
Guards & resolversSeparate route or state in the page?
A route if the screen needs its own link (shareable, back button). Local state for dialogs, dropdowns, ephemeral steps.
Modern routing & lazy loadingHow do I read route parameters?
withComponentInputBinding() + input() in the routed component. No ActivatedRoute and subscribe.
Modern routing & lazy loadingQuality
4Why doesn’t the UI update?
Almost certainly: a plain field changed asynchronously (setTimeout, subscribe) in a zoneless/OnPush app, or an object was mutated. Move to signals and immutable updates.
Change detectionWhere do I handle errors?
Predictable → locally (resource.error()). Cross-cutting (401/500) → interceptor. Rendering failure of an area → @boundary. The rest → global ErrorHandler.
Errors: @boundary & ErrorHandlerWhat do I test, and how?
Stores and mappers: unit tests, no DOM. Dumb components: createComponent + bindings. Pages: fake store + HttpTestingController. Flows: e2e.
Testing with VitestAre my own components accessible?
Build them on Angular Aria (headless): keyboard, focus and correct ARIA; the styling is yours.
Angular Aria