Interview prep · Angular 2026

Land the role, without cramming in the dark.

The questions that actually come up in senior Angular interviews — with clear, up-to-date answers (zoneless, signals, control flow). Expand, revise, repeat.

69questions
8themes
FR · ENbilingual
Angular 22up to date 2026

I bombed two senior Angular interviews on the theory part — even though I'd been shipping to production for years. “As a senior, you're expected to answer these questions easily.” So I gathered everything I was asked. Here are the answers I wish I'd had.

— Sara, founder of NgDigest
69 questions

JS/TS fundamentals

7
An interpreted, dynamically typed, multi-paradigm (imperative, OO, functional), single-threaded language (async via the event loop) that is prototype-based.
Not in the classical sense (Java/C#). It's prototype-based: inheritance via prototype, properties added on the fly. ES6 class is just syntactic sugar over prototypes.
A blueprint defining the structure (properties) and behavior (methods) of objects, with a constructor called on creation.
A concrete object created from a class via new. Analogy: class = mold, instance = cake.
The concrete code fulfilling a contract defined by an interface. The interface says what (signatures), the implementation says how (class X implements Y).
A tree representation of the HTML page, exposed as an API to read/modify content, structure and style. In Angular we avoid direct manipulation and rely on binding and change detection.
A programming interface = a contract specifying how software exchanges data. Types: REST (HTTP), GraphQL, WebSocket (real-time), SOAP (XML, legacy).

Angular Core

21
A TS class decorated with @Component that controls a slice of the UI: decorator (metadata), template (HTML), logic (class).
Modern 20262026: standalone by default (no NgModule), OnPush recommended, input()/output() signal functions.
Smart (container): business logic, injects services, makes calls, passes data down. Dumb (presentational): renders received input(), emits via output(), no services, OnPush, highly reusable.
Yes: parent→child via input(), child→parent via output(), siblings via a shared service.
Modern 20262026: for shared state, a signal-based service rather than a BehaviorSubject.
Layered architecture (presentation/application/domain/infrastructure) + standalone + lazy loading; tooling ESLint + Prettier + Husky + conventional commits; state signals (NgRx if complex); testing unit + E2E + coverage target; CI/CD build/test/deploy pipeline; docs README + Compodoc/Storybook.
Feature-based: core/ (singletons, guards, interceptors), shared/ (reusable components/pipes), features/<context>/{domain,application,infrastructure,presentation}, layout/. Why: scalable, maintainable, lazy-loadable, easy to navigate.
Feature-based (recommended), Layer-based (by technical type, less scalable), Atomic Design (atoms→pages), DDD (by domain, bounded contexts).
Standalone, no hesitation, since Angular 15+ (default since 17). Less boilerplate, explicit per-component imports, loadComponent lazy loading, better tree-shaking. NgModule only survives in legacy code to migrate.
No more zone.js patching async APIs → change detection isn't triggered "magically everywhere". State becomes explicitly reactive via signals (a set/update notifies the framework). Benefits: lighter bundles, more predictable & performant CD.
Modern 2026The date to get right in an interview: provideZonelessChangeDetection() has been stable since Angular 20.2 (August 2025) — not since v22. Since Angular 21, zone.js is no longer part of a new app by default. Calling zoneless "brand new in 2026" signals you haven't kept up.
An @Injectable TS class holding reusable business logic, backend communication (HTTP) and data sharing between components, provided via DI.
A single (singleton) instance app-wide, available everywhere without imports, and tree-shakeable. Alternatives: 'any', route-level providers, or component-level providers: [] for a local instance.
A pattern: dependencies are provided from outside instead of created inside the class. Wins: testability (easy mocks), decoupling, reuse, maintainability.
Modern 20262026: the inject() function is often preferred over constructor injection.
A pattern guaranteeing one instance of a class app-wide. In Angular, providedIn: 'root' creates one automatically. Use cases: AuthService, ConfigService, global cache.
Interpolation {{ }}, property [prop], event (event), two-way [(ngModel)]; plus attribute [attr.x], class [class.active], style [style.color].
In native HTML, disabled is active as soon as it's present, even disabled="false". Use property binding: [disabled]="isDisabled".
Classic: *ngIf (+ else/then), *ngFor (index, first, last, trackBy perf-critical), [ngSwitch]/*ngSwitchCase.
Modern 20262026: use the native control flow @if / @for / @switch (Angular 17+, default) — @for requires a track.
3 syntaxes: object [ngClass]="{active: isActive}" (most common), array ['btn', role], or method getClasses(). For a single class, [class.active]="…" is more direct.
A TS class that alters an element's behavior/appearance. 3 types: component (directive with template), structural (@if/*ngFor), attribute (ngClass, custom via @HostListener/@HostBinding).
A template transformation function. Built-ins: uppercase, number, currency, percent, date, json, and async (auto subscribe/unsubscribe — key). Custom: @Pipe({name, standalone: true}) + transform(). Pure (default, recompute on reference change) vs impure (every CD, ⚠️ perf).
You declare a Routes array (path→component), Angular uses <router-outlet> as a placeholder and swaps content on navigation without a full reload (SPA). Wildcard ** for 404.
A placeholder directive where Angular renders the active route's component (like a photo frame whose image changes with the URL).
Load a component/feature on demand via loadComponent / loadChildren → smaller initial bundle, faster startup, bandwidth saved.

RxJS & Signals

9
An async stream emitting 0..N values over time: push-based, lazy (runs on subscribe), can complete or error (next/error/complete).
A special multicast, hot Observable (emits without subscribers), both Observable and Observer. Variants: Subject, BehaviorSubject (initial + last value), ReplaySubject (last N), AsyncSubject (last on complete).
Everywhere: HttpClient (calls), form valueChanges (with debounceTime/switchMap), router paramMap, and service state. Best consumed with the async pipe.
Modern 20262026, default = signal for synchronous UI state: simple API (set/update/computed), no subscribe/unsubscribe, integrated with zoneless CD, direct value() read. I keep RxJS for genuinely async/event streams (HTTP, debounce, websockets, event orchestration). Interop via toSignal() / toObservable().
Modern 20262026: a root @Injectable service exposing private signals + derived computed + mutation methods (immutable set/update). Legacy approach: private BehaviorSubject + xxx$ = subject.asObservable() + .next([...current, item]).
Creation of/from/interval/timer/fromEvent; transform map/switchMap/mergeMap/concatMap; filtering filter/take/takeUntil/debounceTime/distinctUntilChanged; combination combineLatest/forkJoin/merge; utility tap/catchError/retry.
switchMap: autocomplete (cancel the previous search). mergeMap: fire N independent parallel requests (file uploads). concatMap: preserve order (sequential action queue). exhaustMap: ignore triggers while one is in-flight (anti-double-click on a login button).
Modern 20262026, prefer: the async pipe in templates and takeUntilDestroyed() in classes. Legacy: takeUntil(destroy$) + ngOnDestroy, or manual Subscription. Often, moving to signals removes the problem entirely.
toSignal() subscribes immediately and needs an initial value (else undefined on first render) → set initialValue/type carefully. And toObservable() emits based on an effect: watch for duplicate emissions or timing if you expected strict "current value" semantics.

Architecture & State

11
Yes.
Modern 20262026: signals + computed in a service for small/medium state (often enough). NgRx (Redux: actions/reducers/selectors/effects, DevTools, verbose but scalable) for large apps with complex mutations. Akita = middle ground.
Criteria: sharing (how many features touch the state), mutation complexity, need for traceability/time-travel, team size. Small/medium → signal services. Heavy async side-effects + audit → NgRx (or NgRx SignalStore, which marries signals + structure). Don't over-architect a small app.
A request = method (GET/POST/PUT/PATCH/DELETE) + URL/endpoint + headers (Content-Type, Authorization) + body (POST/PUT/PATCH). Response = status (2xx success, 4xx client error, 5xx server error) + body.
An API whose architecture relies on HTTP: resources addressed by URL, operations via HTTP methods, stateless.
Create / Read / Update / Delete ↔ POST / GET / PUT (or PATCH for partial) / DELETE.
Readable, maintainable code: explicit naming, short single-responsibility functions, DRY, comments only when needed (code self-explains), SOLID principles.
Ports & Adapters: isolate business logic from technical details. The domain (pure) depends on nothing; ports (interfaces) are implemented by adapters (HTTP, DB). Benefits: domain testable without deps, swappable implementations.
A domain-centric approach: Ubiquitous Language (shared dev/business vocabulary), Bounded Contexts, Entities (identity), Value Objects (compared by value), Aggregates, Repository pattern (data-access abstraction).
Web Components: standards (Custom Elements, Shadow DOM, Templates) for framework-agnostic reusable components. Micro-frontends: app split into separately built/deployed features. Pros: autonomous teams, independent deploy; cons: complexity, duplication, perf (multi-bundles). Approaches: iframe, Web Components, Module Federation, Single-SPA.
Custom Element: web standard for custom HTML tags. Angular Elements (@angular/elements, createCustomElement) turns an Angular component into a Web Component usable anywhere (React, Vue, vanilla).
3 paths: Angular Elements (small components), Stencil (framework-agnostic design system), or shared headless logic (pure TS lib) + per-framework UI, sharing styles (CSS/tokens).

Performance

5
The mechanism by which Angular detects state changes and updates the DOM. OnPush: the component is checked only when an input() changes (new ref), an internal event fires, an Observable emits (async pipe), or on markForCheck(). Eager: checks the whole subtree on every event (simple, can be slow). ⚠️ Since Angular 22 (June 2026), OnPush is the DEFAULT strategy: a component that says nothing is OnPush, and the old Default was renamed Eager (the name finally describes what it does). ng update tags existing components as Eager so nothing breaks on migration day.
Modern 2026In interviews the question flips: it is no longer "why move to OnPush?" but "where did you have to keep Eager, and why?" (in-place object mutation, third-party lib writing to state without notifying, code running outside Angular).
Measure (Angular DevTools profiler), then: track on @for (avoid full re-render), OnPush, virtual scroll (cdk-virtual-scroll-viewport), pagination/lazy, avoid impure pipes and heavy template work, memoized computed.
Without a tracking key, Angular destroys/recreates all DOM nodes when the list changes → costly and loses state (focus, animations). With track item.id, it reconciles only what changed.
SSR + hydration (incremental/@defer), NgOptimizedImage for the LCP image, route lazy loading, reduce initial JS (standalone + esbuild tree-shaking), preconnect/preload critical resources, avoid CLS (reserved dimensions).
APM/errors: Sentry, New Relic, Datadog. Logging: ELK, Splunk, CloudWatch. RUM/session: GA, Hotjar, LogRocket. Perf: Lighthouse, WebPageTest, Bundle/Source-Map Analyzer. Angular: Angular DevTools.

Testing & Tooling

10
Write tests before code. Red→Green→Refactor cycle: failing test, minimal code to pass, cleanup. Setup: test framework, follow the cycle, coverage target, CI integration.
Unit (services, pipes, pure functions), integration (component + deps), E2E (critical flows, forms, nav).
Modern 20262026: Vitest as default Angular runner; AAA pattern (Arrange-Act-Assert).
Unit: isolated unit, fast (ms), many, mocked deps. E2E: full app from the user's view, slow (s/min), few, real deps. Follow the test pyramid (many unit, few E2E).
Stable selectors (data-cy/data-testid, no fragile CSS), independent tests, data setup/teardown, explicit waits (no fixed wait), Page Object Pattern.
Order: data-cy/data-testid (best), then stable id, semantic classes as a last resort. Avoid: complex CSS (div > p:nth-child(2)), style classes (.btn-primary), text (fragile with i18n).
Test: business rules, mappers/transformations, stores/state, critical flows. Don't test: the framework itself, third-party internals, generated code, trivial getters. Aim for value, not coverage % for its own sake.
TestBed that imports the standalone component directly (no test module). For signals, set state then read the render/computed (no zone tick in zoneless: trigger CD explicitly). Mock injected services via providers.
The Angular CLI manages the bundler under the hood (config via angular.json, no webpack.config.js). Locally: ng serve (HMR), ng build, ng build --watch. Rare customization via @angular-builders/custom-webpack.
Modern 20262026: the CLI uses esbuild/Vite by default (much faster than Webpack).
Bundling, minification, tree-shaking (removes dead code), code splitting (lazy), HMR, source maps.
Markers that trigger pipeline actions: Git tags (v1.0.0 → prod build/release/deploy), commit-message flags ([ci skip], [deploy]), branch patterns (main, release-*), environment tags (staging/production). Typical pipeline: commit → build → tests → lint → prod build → deploy.

Accessibility

2
Semantic HTML first (button, ul/li), ARIA roles if needed (role="listbox"/option, aria-expanded, aria-activedescendant), full keyboard nav (arrows, Esc, Enter, Tab), visible focus and focus management (Angular CDK a11y: FocusTrap, LiveAnnouncer, cdkTrapFocus), associated labels.
Overusing ARIA where native HTML suffices (<div role="button"> instead of <button>), or aria-* that lies about real state (e.g. aria-hidden on a focusable element). Golden rule: no ARIA is better than bad ARIA.

Soft skills & Lead

4
Answer honestly per your profile: owned frontend Angular expertise (e.g. 80/20, or 70/30 if comfortable with Node/NestJS), adaptability, concrete examples. The message: "I deliver value across the chain; my strength is the front-end."
Onboarding (docs, pair programming, walkthrough), continuous learning (code reviews with constructive feedback, best practices, targeted RxJS/signals/routing sessions), progressive autonomy (increasing task complexity, room to fail), support (availability, regular feedback, not only negative).
Quantitative: PRs merged unaided, falling resolution time, PR acceptance rate, coverage held. Qualitative: autonomy (fewer questions), code quality, architecture proposals. Feedback: junior/team feedback, 1-on-1s. E.g. from 3-4 review round-trips per PR down to 1 in 3 months.
Bring it back to an objective criterion (perf, maintainability, cost, risk), run a spike/POC or a comparative ADR when possible, hear the other's "why", decide by making the trade-off explicit, and commit once decided (disagree & commit). A concrete example from your career beats theory.
Lead magnet · FreeSoon

The Angular interview pack, as a PDF

All 69 questions + answers, laid out to revise offline (train, waiting room, the night before). Just your email, nothing more.

The PDF pack is coming very soon — check back.

See resources