Tags: angular, typescript, rxjs, signals, dependency-injection, components
Level: intermediate
TL;DR: Component-driven frontend framework with two-way binding, hierarchical dependency injection, reactive streams via RxJS, and modern fine-grained reactivity via Signals.
Standalone components eliminate NgModule boilerplate using direct imports.
Signals provide reactive primitives for fine-grained change detection.
RxJS Observables manage asynchronous data streams and event pipelines.
ChangeDetectionStrategy.OnPush triggers rendering only on input reference changes or events.
Hierarchical Dependency Injection scopes services to root, module, or component level.
Structural directives manipulate DOM elements dynamically via micro-syntax.
Reactive Forms supply synchronous, type-safe validation and state tracking.
Content projection distributes child markup using ng-content slots.
Control flow syntax replaces legacy directives with built-in @if, @for, and @switch blocks.
Route guards control navigation lifecycle through functional CanActivate and CanDeactivate handlers.
Q: How do Signals differ from RxJS in modern Angular applications?R: Signals handle synchronous, fine-grained state tracking and template updates without Zone.js overhead. I use RxJS for asynchronous event streams, debouncing, and complex API orchestration, connecting them via toSignal and toObservable.
Q: When should you configure a component with ChangeDetectionStrategy.OnPush?R: I apply OnPush to decouple component trees from global Zone.js dirty-checking cycles. It re-evaluates the view only when input references change, template events fire, or an attached async pipe emits.
Q: What is the difference between providedIn: 'root' and component-level providers?R: ProvidedIn root registers a singleton service accessible across the entire application with automatic tree-shaking. Component-level providers instantiate a new service instance tied exclusively to that component lifecycle and its children.
Forgetting to unsubscribe from RxJS subscriptions in components causes memory leaks; prefer the async pipe or takeUntilDestroyed.
Mutating object properties in place when using OnPush change detection fails to trigger template re-renders.
Calling heavy functions or getters directly inside template expressions executes them on every change detection cycle.
Mixing Signals and Zone.js triggers without understanding execution timing causes unexpected ExpressionChangedAfterItHasBeenCheckedError.
Overusing service singletons for feature-specific state leads to state bleeding across independent routes.
# Create a new Angular application with standalone defaults
ng new angular-app --standalone --routing --style=scss
# Generate a standalone component with OnPush change detection
ng g c features/dashboard --change-detection=OnPush
TypeScript
// Modern standalone component with Signals and new control flow
import { Component, signal, computed, ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'app-counter',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
@if (count() > 0) {
<p>Current count: {{ count() }} (Double: {{ doubleCount() }})</p>
} @else {
<p>Counter is idle.</p>
}
<button (click)="increment()">Increment</button>
`
})
export class CounterComponent {
readonly count = signal(0);
readonly doubleCount = computed(() => this.count() * 2);
increment(): void {
this.count.update(n => n + 1);
}
}
TypeScript
// Cleaning up RxJS subscriptions using takeUntilDestroyed in constructor context
import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({
selector: 'app-data-loader',
standalone: true,
template: `<div>Data fetched successfully</div>`
})
export class DataLoaderComponent {
private readonly http = inject(HttpClient);
constructor() {
this.http.get('/api/resource')
.pipe(takeUntilDestroyed())
.subscribe();
}
}
[ ] Master signal inputs, model inputs, and viewChild signal queries.
[ ] Understand zoneless Angular configuration and hydration with SSR.
[ ] Practice complex RxJS operators: switchMap, mergeMap, concatMap, exhaustMap.
[ ] Review functional interceptors and functional route guards.
[x] Standalone components and built-in template control flow (@if, @for).
[x] Hierarchical Dependency Injection and Injector tree.
Angular Official Documentation (angular.dev)
RxJS Documentation (rxjs.dev)
Angular GitHub Repository (github.com/angular/angular)