AngularAtlased. 22.2

Cap. 02Fundamente moderne08 / 75

@let și expresiile noi din template

Variabile locale cu @let, arrow functions, spread, regex, instanceof, comentarii în tag-uri.

v21v22 ~0 min de citit Documentația oficială

Limbajul de expresii din template s-a apropiat mult de TypeScript în ultimele versiuni. Pe lângă variabilele locale @let, ai acum template literals, regex, spread, arrow functions, instanceof și chiar comentarii în interiorul tag-urilor. Scopul: mai puțin cod „de legătură” în clasă pentru lucruri simple. Bazele de dedesubt — {{ }}, [ ], ( ) și [( )] — sunt la Data binding.

FuncționalitateVersiuneExemplu
@letv18.1 (stabil v19)@let total = price() * qty();
Template literalsv20{{ `Salut ${name()}` }}
**, in, void, typeofv19–v20'x' in obj
Expresii regulatev21 21.0/^\d+$/.test(v)
Spread (array, obiect, argumente)v21 21.1[...a, ...b]
Arrow functionsv21 21.2items.filter(i => i.ok)
instanceofv21 21.2err instanceof HttpErrorResponse
Comentarii în tag-uriv22 22.0<div // notă
?. întoarce undefinedv22 22.0 (breaking)user?.name

@let: variabile locale în template

@let declară o variabilă read-only, vizibilă în blocul curent și în blocurile copil. Se recalculează automat la fiecare randare. E perfect pentru a evita repetarea unei expresii lungi sau a unui async pipe folosit de mai multe ori.

<!-- @let declară o variabilă locală, read-only, vizibilă în blocul curent și în copii -->
@let user = user$ | async;
@let fullName = user?.firstName + ' ' + user?.lastName;
@let isAdmin = user?.roles?.includes('admin') ?? false;

<h1>{{ fullName }}</h1>
@if (isAdmin) { <app-admin-tools /> }

<!-- ideal pentru expresii lungi folosite de mai multe ori -->
@let address = order().customer.billing.address;
<p>{{ address.street }}, {{ address.city }}, {{ address.zip }}</p>

<!-- și în interiorul unui @for, per element -->
@for (p of products(); track p.id) {
  @let finalPrice = p.discount ? p.price * (1 - p.discount) : p.price;
  <span>{{ finalPrice | currency: 'RON' }}</span>
}
Live@let + arrow functions + in + template literal

4 din 5 produse · total 2900 lei

  • Mouse150 lei
  • Tastatură-20%360 lei
  • Căști900 lei
  • Monitor-10%1260 lei
Toată filtrarea e în template. Pentru o listă de 5 produse e perfect; pentru 5.000 ai muta-o într-un computed().

Expresiile noi, pe scurt

<!-- Template literals (v20) -->
<p>{{ `Salut, ${user().name}! Ai ${count()} mesaje.` }}</p>
<img [alt]="`Avatarul lui ${user().name}`" />

<!-- Operatori: ** (putere), in, typeof, void (v20) -->
{{ 2 ** 10 }}
@if ('discount' in product) { ... }
@if (typeof value === 'string') { ... }
<button (click)="void save()">Salvează</button>

<!-- Expresii regulate (v21.0) -->
@let valid = /^07[0-9]{8}$/.test(phone());

<!-- Spread în array-uri, obiecte și argumente (v21.1) -->
@let all = [...defaults, ...extra()];
<app-chart [options]="{ ...baseOptions, color: accent() }" />
{{ max(...values()) }}

<!-- Arrow functions (v21.2) -->
@let done = tasks().filter((t) => t.done);
<app-list [sortFn]="(a, b) => a.name.localeCompare(b.name)" />

<!-- instanceof (v21.2) — clasa trebuie expusă din componentă -->
@if (error() instanceof HttpErrorResponse) { <p>Eroare HTTP {{ error().status }}</p> }
LiveRegex, spread, instanceof, typeof, comentarii în tag
Template literal + regex v21
Telefonul 0712345678 este valid
Spread în array v21.1
angularsignals
instanceof v21.2
● cerc r=2 → arie 12.6
▭ dreptunghi 3×4 → arie 12
● cerc r=1 → arie 3.1
typeof, ** and void
text → string
42 → number
true → boolean
null → object
2 ** 10 = 1024
Fiecare card folosește o funcționalitate de template apărută în v20–v22.

instanceof cere ca clasa să fie expusă

Template-ul vede doar membrii componentei (nu variabilele globale sau importurile), așa că o clasă folosită cu instanceof trebuie pusă într-un câmp.

import { HttpErrorResponse } from '@angular/common/http';

@Component({
  template: `
    @if (error() instanceof HttpErrorResponse) {
      <p>Serverul a răspuns cu {{ error().status }}</p>
    } @else if (error()) {
      <p>Eroare neașteptată</p>
    }
  `,
})
export class ErrorView {
  readonly error = input<unknown>();
  // template-ul vede doar membrii componentei, deci clasa trebuie expusă:
  protected readonly HttpErrorResponse = HttpErrorResponse;
}

Comentarii în interiorul tag-urilor v22

<!-- v22: comentarii în interiorul tag-urilor -->
<button
  // TODO: înlocuiește cu directiva de tooltip
  class="btn"
  /* temporar dezactivat:
  [disabled]="saving()" */
  (click)="save()"
>
  Salvează
</button>

Schimbare importantă în v22: ?. întoarce undefined

Ca să se alinieze cu TypeScript, optional chaining în template întoarce acum undefined (nu null). Migrarea ng update dezactivează temporar diagnosticele nullishCoalescingNotNullable și optionalChainNotNullable ca să nu-ți pice build-ul; reactivează-le după ce verifici template-urile.

<!-- v22 (breaking): ?. în template întoarce undefined, ca în TypeScript (înainte: null) -->
{{ user()?.name }}            <!-- user null → undefined -->

<!-- ✗ comparațiile stricte cu null se schimbă -->
@if (user()?.name === null) { ... }   <!-- acum nu mai e niciodată true -->

<!-- ✓ compară cu == null sau folosește ?? -->
@if (user()?.name == null) { ... }
{{ user()?.name ?? 'Anonim' }}
Acces la membri private (v22.2)

Din v22.2 compilatorul permite template-ului să citească și membri private. Recomandarea din style guide rămâne însă protected pentru tot ce folosește template-ul: e clar că membrul e pentru view, nu API public.

Cât de multă logică pun în template?

// Arrow functions și metode în template rulează la FIECARE change detection a componentei.
// Pentru liste mari sau calcule scumpe, mută logica într-un computed():

// în loc de:   @let done = tasks().filter((t) => t.done);
readonly done = computed(() => this.tasks().filter((t) => t.done)); // memoizat

// Regulă: template-ul ESTE locul pentru expresii simple și locale.
// Logica de business, sortările scumpe și orice se refolosește → în clasă (computed) sau pipe.
În template
  • Formatări scurte, un template literal, o condiție simplă.
  • @let pentru a numi o sub-expresie folosită de mai multe ori.
  • Filtrări mici pe liste scurte, locale vizualizării.
În clasă (computed / metodă) sau pipe
  • Reguli de business („poate utilizatorul să editeze?”).
  • Calcule scumpe sau pe liste mari → computed() (memoizat).
  • Transformări refolosite în multe componente → pipe.
  • Orice ce vrei să testezi unitar.

Capcane frecvente

  • @let nu se poate reasigna și nu e vizibil înainte de declarare.
  • Variabilele globale (Math, JSON, Date, clase importate) nu sunt vizibile în template — expune-le din componentă.
  • {{ { ...obj } }}: un obiect literal în interpolare intră în conflict cu acoladele; folosește-l într-un binding de proprietate sau în @let.

Cap. 02 · 0 din 8 terminate

Ai terminat lecția?

Marcheaz-o și apare pe harta ta: în cuprins și pe prima pagină.

Se marchează singură după ce citești toată lecția.

  1. Standalone & bootstrap
  2. Data binding și evenimente
  3. Control flow: @if, @for, @switch
  4. @let și expresiile noi din template
  5. @defer — lazy loading în template
  6. Class & style bindings
  7. Stilurile componentelor și încapsularea
  8. Pipes: când și cum
Vezi toată harta ta

Toate cele 75 de pagini · scrie ca să filtrezi

  • 01Ce e nou în Angular 21 & 22Toate schimbările importante din v21 și v22, pe scurt, cu link către pagina care le explică.Start
  • 01Prima ta aplicație, pas cu pasO listă de lecturi construită de la o componentă goală la o aplicație terminată — signals, @for, input-uri și output-uri, un serviciu și un formular, pas cu pas.Start
  • 01Decizii rapide„Unde pun asta?”, „Signal sau Observable?”, „Shared sau feature?” — răspunsuri scurte la întrebările de zi cu zi.Start
  • 01Întrebări de interviu Angular60 de întrebări reale de interviu pentru junior, mid și senior, cu răspunsul de dat, întrebarea care urmează și greșelile de evitat. Plus o simulare de interviu.Start
  • 02Standalone & bootstrapCum pornește o aplicație fără NgModule: bootstrapApplication, app.config.ts, imports în componentă.Fundamente moderne
  • 02Data binding și evenimenteInterpolare, binding pe proprietăți și pe atribute, evenimente cu $event și filtre de taste și cum e construit [( )] — ce intră în DOM și ce se întoarce.Fundamente moderne
  • 02Control flow: @if, @for, @switchSintaxa de blocuri care înlocuiește *ngIf/*ngFor/ngSwitch, cu track, @empty și verificare exhaustivă.Fundamente moderne
  • 02@let și expresiile noi din templateVariabile locale cu @let, arrow functions, spread, regex, instanceof, comentarii în tag-uri.Fundamente moderne
  • 02@defer — lazy loading în templateÎncarci componente grele doar când e nevoie: triggere, prefetch, placeholder, loading, error.Fundamente moderne
  • 02Class & style bindingsDe ce [class.x] și [style.x] au înlocuit ngClass și ngStyle (cu migrare automată din v21).Fundamente moderne
  • 02Stilurile componentelor și încapsularea:host, cele trei moduri de încapsulare, teme cu variabile CSS și de ce ::ng-deep e ultima soluție.Fundamente moderne
  • 02Pipes: când și cumPipe pur vs impur, pipe custom și cum alegi între pipe, computed() și o metodă.Fundamente moderne
  • 03signal() și computed()Primitivele reactive: stare scriibilă, stare derivată, egalitate, untracked și reguli de imutabilitate.Signals & reactivitate
  • 03effect() — când DA, când NUEfecte secundare sincronizate cu semnale: localStorage, logging, API-uri imperative. Și capcanele lor.Signals & reactivitate
  • 03linkedSignal() — stare derivată editabilăUn semnal care se resetează când se schimbă sursa, dar pe care îl poți și seta manual.Signals & reactivitate
  • 03resource, rxResource, httpResourceDate asincrone ca semnale: status, value, error, reload, anulare automată. Stabile din v22.Signals & reactivitate
  • 03debounced() — semnale cu întârziereVarianta „debounce” a unui semnal, fără RxJS. Perfect pentru căutare.Signals & reactivitate
  • 03Liste: căutare, filtrare, sortare, paginareUn lanț de computed-uri care recalculează doar ce s-a schimbat, cu filtrele ținute în URL, ca un link să redeschidă aceeași vedere.Signals & reactivitate
  • 03Observables de la zeroCe e un Observable, subscribe și unsubscribe, operatorii pe care îi folosești în fiecare săptămână, cold vs hot — și când ajunge un signal.Signals & reactivitate
  • 03Signals ↔ RxJStoSignal, toObservable, takeUntilDestroyed, outputFromObservable — și când RxJS rămâne alegerea bună.Signals & reactivitate
  • 04input() și output()Inputuri ca semnale (required, transform, alias) și outputuri tipizate. Data down, events up.Componente: comunicare
  • 04model() — two-way bindingBanana-in-a-box [( )] cu un singur API. Când îl folosești și când e mai bine input + output.Componente: comunicare
  • 04viewChild & contentChildInterogări ca semnale: viewChild, viewChildren, contentChild, contentChildren, opțiunea read.Componente: comunicare
  • 04Lifecycle & DestroyRefCe hook-uri mai contează în era signals, afterNextRender, DestroyRef și ngOnChanges tipizat.Componente: comunicare
  • 04Content projectionng-content cu select, sloturi multiple, conținut implicit și capcana proiecției condiționale.Componente: comunicare
  • 04ng-template & ngTemplateOutletTemplate-uri ca valori: render props în Angular, context tipizat și personalizare de componente.Componente: comunicare
  • 05Smart vs DumbContainer vs presentational: cine ține starea, cine doar afișează, și cum le împarți corect.Design de componente
  • 05Componente generice <T>Un DataTable<T> sau Select<T> tipizat corect, cu template-uri pentru celule.Design de componente
  • 05Componente dinamiceNgComponentOutlet, createComponent cu inputBinding/outputBinding și un dashboard construit din config.Design de componente
  • 05Directive & host compositionDirective atribut, metadata host: {} și Directive Composition API (hostDirectives).Design de componente
  • 05Controale custom de formularFormValueControl (Signal Forms) vs ControlValueAccessor: un rating cu stele, în ambele variante.Design de componente
  • 05Change detectionOnPush e implicit din v22, zone.js lipsește din v21. Ce declanșează randarea și cum să nu te arzi.Design de componente
  • 06inject() & @Service()Noul decorator @Service() din v22, inject() vs constructor și contextul de injecție.Dependency Injection
  • 06Providers & ierarhia de injectoriRoot vs rută vs componentă, useClass/useValue/useFactory/useExisting și modificatorii optional/self/skipSelf.Dependency Injection
  • 06InjectionToken & provideX()Configurare tipizată, funcții provideFeature(), makeEnvironmentProviders și inițializatori.Dependency Injection
  • 06injectAsync() — servicii lazyÎncarci un serviciu greu abia când ai nevoie de el, cu prefetch la idle.Dependency Injection
  • 07Structura de folderecore / shared / features, ce intră în fiecare și cum arată un feature pe dinăuntru.Arhitectura aplicației
  • 07Shared vs featureCând muți o componentă în shared și (mai ales) când NU. Checklist concret.Arhitectura aplicației
  • 07Interfețe & modeleInterfață inline sau fișier separat? DTO vs model de domeniu, type vs interface, unde le pui.Arhitectura aplicației
  • 07State management cu signalsStore-uri simple pe semnale, facade, stare locală vs globală și când îți trebuie NgRx.Arhitectura aplicației
  • 07Style guide & namingConvențiile oficiale actuale: nume de fișiere fără sufixe, protected, readonly, ordinea membrilor.Arhitectura aplicației
  • 07Barrels, aliasuri & granițeindex.ts, path aliases, API public pe feature și reguli de dependență care se pot verifica automat.Arhitectura aplicației
  • 07Erori: @boundary & ErrorHandlerNoul bloc @boundary din v22.2, ErrorHandler global, erori HTTP și erori din resource.Arhitectura aplicației
  • 08Routing modern & lazy loadingloadComponent, rute copil, parametri ca input-uri și moștenirea parametrilor (default nou în v22).Routing
  • 08Guards & resolverscanActivate, canMatch, canDeactivate și resolve ca funcții, cu redirect prin UrlTree / RedirectCommand.Routing
  • 09Signal Forms — bazeleFormulare construite pe semnale: form(), [formField], validare prin schemă. Stabile din v22.Formulare
  • 09Signal Forms — avansatValidare custom și cross-field, async/HTTP cu debounce, liste dinamice, disabled/hidden, scheme reutilizabile.Formulare
  • 09Reactive Forms tipizateFormGroup tipizat, nonNullable, FormArray — și cum conviețuiesc cu Signal Forms.Formulare
  • 10HttpClient, interceptors & API layerHttpClient fără setup (v21), Fetch implicit (v22), interceptori funcționali și stratul de API cu mapare DTO.HTTP & date
  • 11Performanță — checklistCe chiar contează: OnPush + signals, track, @defer, lazy routes, imagini, bundle și hidratare.Calitate & performanță
  • 11Testare cu VitestVitest e runner-ul implicit din v21. TestBed, componente cu semnale, servicii, HTTP și harness-uri.Calitate & performanță
  • 11DevTools: cum te uiți în aplicațieChrome DevTools și Angular DevTools pas cu pas: ce arată fiecare panou, cu exerciții care merg chiar pe site-ul ăsta.Calitate & performanță
  • 11Angular AriaComponente headless, accesibile, pe care le stilizezi cum vrei: tabs, accordion, menu, listbox...Calitate & performanță
  • 12SSR, prerender & render modesCând randezi pe server, când la build și când doar în browser: RenderMode pe rută, app.routes.server.ts și costurile reale.SSR & hidratare
  • 12Hidratare: event replay & incrementalCum preia browserul HTML-ul de pe server fără să-l refacă: hidratare completă, event replay, @defer (hydrate on …) și erorile de nepotrivire.SSR & hidratare
  • 12Cod compatibil cu serverulwindow nu există pe server: PLATFORM_ID, afterNextRender, DOCUMENT, TransferState, cache-ul HTTP și PendingTasks.SSR & hidratare
  • 13Micro frontendsCând merită să spargi o aplicație în mai multe deploy-uri și când e doar complexitate: Native Federation, Module Federation, iframes, Web Components.Arhitectură la scară
  • 13Web Components cu Angular ElementscreateCustomElement: o componentă Angular folosită ca tag HTML oriunde, plus comunicarea între aplicații prin evenimente și BroadcastChannel.Arhitectură la scară
  • 13Monorepo, librării & granițeUn workspace cu mai multe aplicații și librării: ng generate library, Nx, entry points secundare, publicare și reguli de dependență.Arhitectură la scară
  • 13Arhitectură hexagonală (ports & adapters)Domeniul fără Angular, porturi ca clase abstracte și adaptoare interschimbabile: HTTP, localStorage sau in-memory, fără să atingi UI-ul.Arhitectură la scară
  • 14Semnalele pe dinăuntruGraful reactiv: producători și consumatori, push-pull, de ce computed e lazy și glitch-free, problema diamantului și când rulează efectele.Reactivitate avansată
  • 14RxJS avansat: operatori de ordin superiorswitchMap, mergeMap, concatMap și exhaustMap pe o diagramă live, plus retry cu backoff, shareReplay și cum eviți scurgerile.Reactivitate avansată
  • 14NgRx SignalStoreState management la scară pe semnale: withState, withComputed, withMethods, rxMethod, entități și hooks — și când un store simplu e suficient.Reactivitate avansată
  • 14Mașini de stări cu signalsFără stări imposibile: o mașină tipizată pe signals, cu tranziții, guards și diagrama stărilor, live.Reactivitate avansată
  • 15WebSockets: timp real care rezistă rețeleiUn socket tipizat ca signals: reconectare cu backoff și jitter, heartbeat, coadă de mesaje cât ești offline și siguranță la SSR.Timp real și offline
  • 15Actualizări optimiste și rollbackInterfață instantanee, dar onestă: snapshot și rollback, răspunsuri sosite în altă ordine, chei de idempotență.Timp real și offline
  • 15Offline-first: Service Worker și cacheService Worker-ul Angular: strategii de cache, anunțarea versiunilor noi și o coadă pentru modificările făcute offline.Timp real și offline
  • 16Web WorkersCalcule grele fără să blochezi interfața: un worker real în pagină, comunicare prin mesaje și când nu merită.UI & performanță avansată
  • 16Liste uriașe: virtual scroll100.000 de rânduri fără lag: CDK virtual scroll, itemSize, trackBy și alternativele (paginare, infinite scroll).UI & performanță avansată
  • 16Animații moderne & View Transitionsanimate.enter și animate.leave în locul @angular/animations (depreciat), tranziții CSS și View Transitions la navigare.UI & performanță avansată
  • 16Memory leaks: cum le găsești și le repariSubscripții, timere și listeneri care trăiesc mai mult decât componenta lor — cum îi vezi în DevTools și cum îi închizi.UI & performanță avansată
  • 17Securitate: XSS, sanitizare & CSPCe face Angular automat împotriva XSS, când devine periculos bypassSecurityTrust, plus CSP cu nonce, Trusted Types și XSRF.Securitate & globalizare
  • 17Autentificare: token-uri & refreshUn interceptor care atașează token-ul, reîmprospătează o singură dată la 401 și reia cererile din coadă — plus unde ții token-ul.Securitate & globalizare
  • 17OAuth 2.1 și OpenID Connect cu PKCEFluxul authorization code cu PKCE, pas cu pas: verifier și challenge, state și nonce, ID token-ul și de ce un BFF e mai sigur.Securitate & globalizare
  • 17Internaționalizare (i18n)$localize, atributul i18n, ICU plural/select, build per limbă vs. traduceri la runtime și formatarea după locale.Securitate & globalizare