Angular — Cheat Sheet

Tag: angular, typescript, rxjs, signals, dependency-injection, frontend

Livello: intermedio

TL;DR: Sintesi rapida su architettura a componenti, reattivita' con Signals e RxJS, Dependency Injection e ciclo di vita.

Concetti chiave

Component-based architecture basata su TypeScript e template dichiarativi HTML.

Change Detection gestita storicamente da Zone.js e ottimizzabile con OnPush.

Angular Signals introduce una reattivita' fine-grained senza dipendere da Zone.js.

Dependency Injection gerarchica configurabile a livello di root, modulo o componente.

RxJS integrato per flussi asincroni, gestione eventi e chiamate HTTP.

Routing con supporto a lazy loading, functional guards e resolvers.

Standalone components eliminano la necessita' obbligatoria dei NgModules.

Due approcci per i form: Template-driven forms e Reactive forms tipizzati.

Direttive strutturali e di attributo per manipolare DOM e comportamenti.

Lifecycle hooks principali: ngOnInit, ngOnChanges, ngAfterViewInit e ngOnDestroy.

Domande tipiche e risposte pronte

Q: Qual e' la differenza tra ChangeDetectionStrategy.Default e OnPush?R: Default controlla il componente a ogni evento asincrono globale. Con OnPush il check scatta solo se cambiano i riferimenti degli @Input(), viene emesso un evento interno o si usa un Signal/async pipe.

Q: Quando usi i Signals rispetto agli Observable di RxJS?R: Uso Signals per lo stato sincrono e la reattivita' locale della UI. Mantengo RxJS per flussi asincroni complessi, debounce di eventi, websocket e pipeline HTTP.

Q: Come gestisci la pulizia delle subscription per evitare memory leak?R: Preferisco takeUntilDestroyed() nel context di iniezione oppure la async pipe nel template, evitando subscription manuali non chiuse in ngOnDestroy.

Insidie e errori comuni

Mancata cancellazione delle subscription manuali di RxJS che causa memory leak persistenti.

Mutazione diretta degli oggetti in input con strategia OnPush senza cambiare il riferimento in memoria.

Utilizzo eccessivo di metodi invocati direttamente nel template, valutati a ogni ciclo di change detection.

Creazione di istanze multiple di un service per mancata comprensione della gerarchia degli injectors.

Esposizione di WritableSignal fuori dal service anziche' esporre la versione sola lettura asReadonly().

Snippet e comandi

# Creazione nuovo progetto standalone con routing
npx @angular/cli new my-app --standalone --routing --style=scss

# Generazione componente standalone
npx @angular/cli g c components/user-card

TypeScript

// Componente standalone con Signals e computed
import { Component, signal, computed } from '@angular/core';

@Component({
  selector: 'app-counter',
  standalone: true,
  template: `
    <button (click)="increment()">Incrementa: {{ count() }}</button>
    <p>Doppio: {{ double() }}</p>
  `
})
export class CounterComponent {
  readonly count = signal<number>(0);
  readonly double = computed(() => this.count() * 2);

  increment(): void {
    this.count.update(n => n + 1);
  }
}

TypeScript

// Service iniettabile in root con gestione stato tramite Signal
import { Injectable, signal } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class UserService {
  private readonly userState = signal<string | null>(null);
  readonly currentUser = this.userState.asReadonly();

  setUser(name: string): void {
    this.userState.set(name);
  }
}

Da ripassare

[ ] Meccanismo interno di interazione tra Signals e ChangeDetection OnPush

[ ] Nuove sintassi control flow: @if, @for con blocco @empty, @switch

[ ] Deferrable views con sintassi @defer (on viewport)

[x] Dependency injection gerarchica e scope dei provider (providedIn: 'root')

[x] Operatori RxJS comuni: switchMap, mergeMap, concatMap, exhaustMap

Jarvis Interviews
Jarvis