Fondamentaux JS/TS
7class ES6 ne sont que du sucre syntaxique au-dessus des prototypes.constructor appelé à la création.new. Analogie : classe = moule, instance = gâteau.interface. L'interface dit quoi (signatures), l'implémentation dit comment (class X implements Y).Angular Core
21@Component qui contrôle une portion de l'UI : un décorateur (métadonnées), un template (HTML) et de la logique (classe).NgModule), OnPush recommandé, input()/output() en fonctions signal.input() reçus, émet via output(), pas de service, OnPush, hautement réutilisable.input(), enfant→parent via output(), siblings via un service partagé.BehaviorSubject.core/ (singletons, guards, interceptors), shared/ (composants/pipes réutilisables), features/<contexte>/{domain,application,infrastructure,presentation}, layout/. Pourquoi : scalable, maintenable, lazy-loadable, on trouve vite le code.loadComponent, meilleur tree-shaking. Les NgModule ne restent que pour du legacy à migrer.zone.js qui patche les API async → la change detection n'est plus déclenchée « automatiquement partout ». On rend l'état explicitement réactif via signals (un set/update notifie le framework). Bénéfices : bundles plus légers, CD plus prévisible et performante.provideZonelessChangeDetection() est stable depuis Angular 20.2 (août 2025) — pas depuis la v22. Depuis Angular 21, zone.js n'est plus inclus dans une app neuve par défaut. Dire « zoneless c'est tout neuf en 2026 » te fait passer pour quelqu'un qui n'a pas suivi.@Injectable qui porte la logique métier réutilisable, la communication backend (HTTP) et le partage de données entre composants, fournie via la DI.'any', providers au niveau d'une route, ou providers: [] au niveau d'un composant pour une instance locale.inject() en fonction est souvent préféré à l'injection par constructeur.providedIn: 'root' en crée un automatiquement. Use cases : AuthService, ConfigService, cache global.{{ }}, property [prop], event (event), two-way [(ngModel)] ; plus attribute [attr.x], class [class.active], style [style.color].disabled est actif dès qu'il est présent, même disabled="false". Il faut le property binding : [disabled]="isDisabled".*ngIf (+ else/then), *ngFor (index, first, last, trackBy crucial perf), [ngSwitch]/*ngSwitchCase.@if / @for / @switch (Angular 17+, recommandé/par défaut) — @for exige un track.[ngClass]="{active: isActive}" (le plus courant), tableau ['btn', role], ou méthode getClasses(). Pour une seule classe, [class.active]="…" est plus direct.@if/*ngFor), attribut (ngClass, custom via @HostListener/@HostBinding).uppercase, number, currency, percent, date, json, et async (subscribe/unsubscribe auto — clé). Custom : @Pipe({name, standalone: true}) + transform(). Pure (défaut, recalcul si la référence change) vs impure (chaque CD, ⚠️ perf).Routes (path→component), Angular utilise <router-outlet> comme emplacement, et remplace le contenu à la navigation sans recharger la page (SPA). Wildcard ** pour le 404.loadComponent / loadChildren → bundle initial plus petit, démarrage plus rapide, bande passante économisée.RxJS & Signals
9subscribe), peut compléter ou émettre une erreur (next/error/complete).Subject, BehaviorSubject (valeur initiale + dernière valeur), ReplaySubject (N dernières), AsyncSubject (dernière à la complétion).HttpClient (appels), valueChanges des forms (avec debounceTime/switchMap), paramMap du router, et état via service. À consommer de préférence avec le pipe async.set/update/computed), pas de subscribe/unsubscribe, intégré à la CD zoneless, lecture directe value(). Je garde RxJS pour le vrai asynchrone événementiel (flux HTTP, debounce, websockets, orchestration d'événements). Interop via toSignal() / toObservable().@Injectable({providedIn:'root'}) exposant des signals privés + computed dérivés + méthodes de mutation (set/update immuables). Approche legacy : BehaviorSubject privé + xxx$ = subject.asObservable() + .next([...current, item]).of/from/interval/timer/fromEvent ; transfo map/switchMap/mergeMap/concatMap ; filtrage filter/take/takeUntil/debounceTime/distinctUntilChanged ; combinaison combineLatest/forkJoin/merge ; utilitaires tap/catchError/retry.async dans le template, et takeUntilDestroyed() dans la classe. Legacy : takeUntil(destroy$) + ngOnDestroy, ou Subscription manuelle. Souvent, passer aux signals supprime carrément le problème.toSignal() subscribe immédiatement et a besoin d'une valeur initiale (sinon undefined au premier rendu) → bien typer/initialValue. Et toObservable() émet sur la base de l'effet : attention aux émissions en doublon ou au timing si on attendait une sémantique « valeur courante » stricte.Architecture & État
11computed dans un service pour petit/moyen état (souvent suffisant). NgRx (Redux : actions/reducers/selectors/effects, DevTools, verbeux mais scalable) pour grosse app avec mutations complexes. Akita = intermédiaire.@angular/elements, createCustomElement) convertit un composant Angular en Web Component utilisable partout (React, Vue, vanilla).Performance
5input() change (nouvelle réf), qu'un événement interne survient, qu'un Observable émet (async pipe), ou sur markForCheck(). Eager : vérifie tout le sous-arbre à chaque événement (simple, peut être lent). ⚠️ Depuis Angular 22 (juin 2026), OnPush est la stratégie PAR DÉFAUT : un composant qui ne dit rien est en OnPush, et l'ancien Default a été renommé Eager (le nom décrit enfin ce que la stratégie fait). ng update tague les composants existants en Eager pour que rien ne casse le jour de la migration.Eager, et pourquoi ? » (mutation d'objet en place, lib tierce qui écrit dans le state sans notifier, code hors zone Angular).track sur @for (évite de re-render tout), OnPush, virtual scroll (cdk-virtual-scroll-viewport), pagination/lazy, éviter les pipes impurs et le travail lourd dans le template, computed mémoïsé.track item.id, il réconcilie uniquement ce qui a changé.@defer), NgOptimizedImage pour le LCP image, lazy loading des routes, réduire le JS initial (standalone + tree-shaking esbuild), preconnect/preload des ressources critiques, éviter le CLS (dimensions réservées).Tests & Tooling
10data-cy/data-testid, pas de CSS fragile), tests indépendants, setup/teardown des données, attentes explicites (pas de wait fixe), Page Object Pattern.data-cy/data-testid (meilleur), puis id stable, classes sémantiques en dernier recours. À éviter : CSS complexe (div > p:nth-child(2)), classes de style (.btn-primary), texte (fragile en i18n).TestBed qui importe le composant standalone directement (plus de module de test). Pour les signals, on set l'état puis on lit le rendu/computed (pas de tick zone en zoneless : déclencher la CD explicitement). Mocker les services injectés via providers.angular.json, pas de webpack.config.js). En local : ng serve (HMR), ng build, ng build --watch. Customisation rare via @angular-builders/custom-webpack.v1.0.0 → build prod/release/deploy), flags dans les messages de commit ([ci skip], [deploy]), patterns de branches (main, release-*), environment tags (staging/production). Pipeline type : commit → build → tests → lint → build prod → deploy.Accessibilité
2button, ul/li), rôles ARIA si besoin (role="listbox"/option, aria-expanded, aria-activedescendant), navigation clavier complète (flèches, Échap, Entrée, Tab), focus visible et focus management (Angular CDK a11y : FocusTrap, LiveAnnouncer, cdkTrapFocus), labels associés.<div role="button"> au lieu de <button>), ou poser des aria-* qui mentent sur l'état réel (ex aria-hidden sur un élément focusable). Règle d'or : no ARIA is better than bad ARIA.