AngularAtlasAusg. 22.2

Kap. 03Signals & Reaktivität13 / 75

signal() und computed()

Die reaktiven Grundbausteine: beschreibbarer Zustand, abgeleiteter Zustand, Gleichheit, untracked und Regeln zur Immutability.

stabil ~0 Min. Lesezeit Offizielle Doku

Ein Signal ist eine Box, die einen Wert hält und alle, die ihn gelesen haben, automatisch benachrichtigt, sobald er sich ändert. Angular führt Buch: Wenn das Template, ein computed() oder ein effect() count() liest, hängt es von diesem Signal ab. Ändert sich count, wird nur aktualisiert, was davon abhängt — ohne Zone.js und ohne Prüfung des gesamten Komponentenbaums.

Warum das in 21 & 22 wichtig ist

Ab v21 sind neue Anwendungen zoneless, und ab v22 sind Komponenten standardmäßig OnPush. Signals sind also keine „moderne Option“ mehr — sie sind der zentrale Mechanismus, über den Angular weiß, was neu gerendert werden muss. Wenn du Zustand in einfachen Feldern hältst und ihn aus einem setTimeout oder einem subscribe heraus änderst, aktualisiert sich die UI womöglich nicht mehr.

Die drei Grundoperationen

Du erstellst ein Signal mit signal(initialValue), liest es, indem du es wie eine Funktion aufrufst, und schreibst mit set() oder update(). Abgeleiteter Zustand entsteht mit computed().

import { computed, signal, Signal, WritableSignal } from '@angular/core';

const name: WritableSignal<string> = signal('Ana');

name();                        // Lesen → 'Ana'
name.set('Maria');             // direktes Schreiben
name.update((n) => n.toUpperCase()); // Schreiben auf Basis des alten Werts

const greeting: Signal<string> = computed(() => `Hallo, ${name()}!`);
greeting();                    // 'Hallo, MARIA!'
// greeting.set(...)           ✗ ein computed ist schreibgeschützt

const readonlyName: Signal<string> = name.asReadonly(); // ohne Schreibzugriff freigegeben
LiveCounter mit abgeleitetem Zustand
0
  • double() = 0
  • parity() = gerade
  • computed neu berechnet: 1 Mal (nur wenn sich count geändert hat)
Beobachte den Neuberechnungs-Zähler: Das computed läuft nicht bei jedem Rendern, sondern nur, wenn sich count ändert.

Was du über computed() wissen solltest

  • Lazy: Es wird erst berechnet, wenn es jemand liest.
  • Memoisiert: Haben sich die Abhängigkeiten nicht geändert, liefert es den gecachten Wert — egal wie oft du es liest.
  • Dynamische Abhängigkeiten: Es verfolgt nur die Signals, die beim letzten Durchlauf tatsächlich gelesen wurden. Bei cond() ? a() : b() werden Änderungen an b ignoriert, solange cond true ist.
  • Pur: keine Seiteneffekte (kein HTTP, kein set() auf anderen Signals, kein DOM).

Die goldene Regel: abgeleiteter Zustand = computed()

Jeder Wert, der sich aus anderem Zustand berechnen lässt, wird nicht separat gespeichert. Die Summe eines Warenkorbs, die gefilterte Liste, „ist das Formular gültig“, „hat der Benutzer Admin-Rechte“ — das alles sind computed(). Eine einzige Quelle der Wahrheit, keine manuelle Synchronisierung.

interface CartItem {
  id: number;
  name: string;
  price: number;
  qty: number;
}

export class Cart {
  protected readonly items = signal<CartItem[]>([]);
  protected readonly filter = signal('');

  // ✓ Alles, was sich aus etwas anderem berechnen lässt = computed()
  protected readonly visible = computed(() =>
    this.items().filter((i) => i.name.toLowerCase().includes(this.filter().toLowerCase())),
  );
  protected readonly subtotal = computed(() =>
    this.items().reduce((sum, i) => sum + i.price * i.qty, 0),
  );
  protected readonly vat = computed(() => Math.round(this.subtotal() * 0.19));
  protected readonly total = computed(() => this.subtotal() + this.vat());
  protected readonly freeShipping = computed(() => this.subtotal() >= 1000);

  protected changeQty(id: number, delta: number): void {
    this.items.update((items) =>
      items.map((i) => (i.id === id ? { ...i, qty: Math.max(0, i.qty + delta) } : i)),
    );
  }
}
LiveWarenkorb: 1 Daten-Signal + 6 computeds
ProduktPreisMengeTotal
Mechanische Tastatur450 RON
1
450 RON
Ergonomische Maus220 RON
0
0 RON
Monitor 27"1300 RON
0
0 RON
USB-C-Hub160 RON
2
320 RON
Artikel: 3Subtotal: 770 RONMwSt. 19 %: 146 RONTotal: 916 RONNoch 230 RON für Gratis-Versand
Du änderst nur items. Gefilterte Liste, Zwischensumme, MwSt., Gesamtsumme und kostenloser Versand werden automatisch abgeleitet.
So (abgeleitet)
// ✓ Eine einzige Quelle der Wahrheit, der Rest wird abgeleitet
export class Cart {
  readonly items = signal<CartItem[]>([]);
  readonly total = computed(() => this.items().reduce((s, i) => s + i.price, 0));

  add(item: CartItem) {
    this.items.update((list) => [...list, item]);
  }

  remove(id: number) {
    this.items.update((list) => list.filter((i) => i.id !== id));
  }
}
Nicht so (gespeichert + synchronisiert)
// ✗ Abgeleiteter Zustand wird GESPEICHERT und von Hand synchronisiert
export class Cart {
  items = signal<CartItem[]>([]);
  total = signal(0);

  add(item: CartItem) {
    this.items.update((list) => [...list, item]);
    this.total.set(this.total() + item.price); // leicht vergessen, leicht nicht mehr synchron
  }

  remove(id: number) {
    this.items.update((list) => list.filter((i) => i.id !== id));
    // Bug: Wir haben vergessen, total zu aktualisieren
  }
}

// ✗ Genauso schlecht: ein effect, der einen Wert in ein anderes Signal „kopiert“
effect(() => this.total.set(this.items().reduce((s, i) => s + i.price, 0)));

Immutability: warum push() nicht funktioniert

Ein Signal entscheidet, ob es sich geändert hat, indem es den alten und den neuen Wert mit Object.is vergleicht, also per Referenz. Wenn du ein Array oder ein Objekt an Ort und Stelle veränderst, bleibt die Referenz gleich und niemand wird benachrichtigt. Das Template rendert vielleicht zufällig neu (zum Beispiel weil du in der Komponente irgendwo geklickt hast), aber die computed()s behalten den alten Wert. Das Ergebnis: eine teilweise aktualisierte UI — der am schwersten zu findende Bug.

LiveMutation vs. immutables Update
Gerenderte Liste (tags())
tag-1tag-2
count = computed(() => tags().length)
2
Drück ein paarmal auf push(): Die Liste rendert beim Klick neu, aber das computed hinkt hinterher.
const tags = signal(['a', 'b']);

// ✗ Mutation: dieselbe Array-Referenz → Angular erfährt NICHTS
tags().push('c');
tags.set(tags()); // hilft trotzdem nicht: Object.is(alt, neu) === true

// ✓ Immer eine neue Referenz
tags.update((t) => [...t, 'c']);                    // hinzufügen
tags.update((t) => t.filter((x) => x !== 'a'));     // entfernen
tags.update((t) => t.map((x) => (x === 'b' ? 'B' : x))); // ändern

const user = signal({ name: 'Ana', address: { city: 'Cluj' } });
// ✗ user().address.city = 'Iași';
// ✓
user.update((u) => ({ ...u, address: { ...u.address, city: 'Iași' } }));

Eigene Gleichheit mit equal

Manchmal bekommst du ein neues Objekt, das logisch „dasselbe“ ist (zum Beispiel von einer API oder aus einem Formular). Mit der Option equal vermeidest du unnötige Benachrichtigungen und Neuberechnungen.

import { signal } from '@angular/core';

interface Filters {
  query: string;
  page: number;
}

// Standardmäßig: Gleichheit über Object.is (Referenz).
// Mit `equal` entscheidest du, wann zwei Werte „gleich“ sind → keine sinnlosen Benachrichtigungen.
const filters = signal<Filters>(
  { query: '', page: 1 },
  { equal: (a, b) => a.query === b.query && a.page === b.page },
);

filters.set({ query: '', page: 1 }); // neues Objekt, aber „gleich“ → NIEMAND wird benachrichtigt

// Funktioniert auch bei computed:
const ids = computed(() => users().map((u) => u.id), {
  equal: (a, b) => a.length === b.length && a.every((id, i) => id === b[i]),
});
Liveequal: dieselben Filter als neues Objekt – wer lädt die Liste neu?
{ query: 'angular', page: 1 }
signal(filters)

1Ladevorgänge der Liste

  1. Ladevorgang #1 · Seite 1
signal(filters, { equal })

1Ladevorgänge der Liste

  1. Ladevorgang #1 · Seite 1
Jede Karte hat einen Effect, der für ein Neuladen der Liste steht (wie ein httpResource, der neu lädt). Mit equal benachrichtigt ein neues Objekt mit denselben Werten niemanden.

untracked(): Lesen ohne Abhängigkeit

Innerhalb eines computed oder effect wird jedes gelesene Signal zur Abhängigkeit. Wenn du nur den aktuellen Wert brauchst, ohne bei dessen Änderung erneut zu laufen, verwende untracked().

import { effect, signal, untracked } from '@angular/core';

const user = signal('Ana');
const theme = signal('dark');

effect(() => {
  // Abhängigkeit: user — der Effect läuft erneut, wenn sich user ändert
  const name = user();

  // Lesen OHNE Abhängigkeit: Eine Änderung des Themes führt den Effect NICHT erneut aus
  const currentTheme = untracked(theme);

  console.log(`[analytics] ${name} hat die Seite geöffnet (Theme: ${currentTheme})`);
});

// untracked akzeptiert auch eine Funktion — praktisch, wenn du Code aufrufst, der intern Signals liest
effect(() => {
  const id = selectedId();
  untracked(() => this.logger.log(`Ausgewählt: ${id}`)); // der Logger darf beliebige Signals lesen
});
Liveuntracked(): Welcher Effect läuft erneut, wenn sich das Theme ändert?
usertheme
const t = theme();Läufe: 1
  1. Ana hat die Seite geöffnet (Theme: dark)
const t = untracked(theme);Läufe: 1
  1. Ana hat die Seite geöffnet (Theme: dark)
Beide Effects protokollieren Nutzer und Theme, wie das Analytics-Beispiel oben. Der zweite liest das Theme mit untracked(): Er sieht immer das aktuelle Theme, aber ein Theme-Wechsel startet ihn nicht neu.

Signals in Services: privat schreiben, öffentlich lesen

Das Grundmuster für jeden geteilten Zustand: Das beschreibbare Signal ist private, nach außen gibst du asReadonly() und computed()s frei, und Änderungen laufen über Methoden mit klaren Namen. Alle Details findest du auf der Seite State Management.

import { Service, computed, signal } from '@angular/core';

@Service()
export class CounterStore {
  // Schreiben ist privat: Nur der Store ändert seinen Zustand …
  private readonly _count = signal(0);

  // … und nach außen gibst du nur das Lesen frei.
  readonly count = this._count.asReadonly();
  readonly isZero = computed(() => this._count() === 0);

  increment(): void {
    this._count.update((c) => c + 1);
  }
}

Wann ja, wann nein

signal / computed verwenden
  • Der Zustand einer Komponente (Filter, Auswahl, Umschalter, die aktuelle Seite).
  • Geteilter Zustand in einem Service / Store.
  • Jeder Wert, der im Template angezeigt wird.
  • Abgeleitete Werte: Summen, gefilterte Listen, Flags (computed).
  • Inputs von Komponenten (input() ist ebenfalls ein Signal).
Nicht das richtige Werkzeug
  • Ströme von Events über die Zeit (WebSocket, Drag, Tippen mit komplexen Operatoren) — dort ist RxJS ausdrucksstärker. Siehe Signals ↔ RxJS.
  • Asynchrone Daten vom Server — nutze resource / httpResource statt eines Signals, das du per Hand aus einem subscribe setzt.
  • Konstanten, die sich nie ändern — ein einfaches readonly reicht.
  • „Editierbarer“ abgeleiteter Zustand (eine Auswahl, die sich zurücksetzt) — nutze linkedSignal.

Häufige Stolperfallen

  • Du vergisst die Klammern: {{ count }} zeigt die Funktion an, nicht den Wert. Richtig: {{ count() }}.
  • Du mutierst, statt zu ersetzen: push, splice, obj.x = 1 benachrichtigen nicht.
  • Seiteneffekte in computed: Ein computed, das einen HTTP-Call macht oder ein anderes Signal setzt, ist ein Bug, der nur darauf wartet, aufzutreten.
  • Async in computed: computed(async () => ...) liefert ein Promise, nicht den Wert. Verwende resource().
  • Du liest nur einmal: const x = this.count(); im Konstruktor ist eine Momentaufnahme, keine reaktive Verbindung.
  • Synchronisieren mit effect: effect(() => b.set(a() * 2)) → verwende computed (oder linkedSignal, wenn b auch beschreibbar sein muss).

Spickzettel

// ERSTELLEN
const a = signal(0);                       // WritableSignal<number>
const b = signal<User | null>(null);       // expliziter Typ, wenn du mit null startest
const c = computed(() => a() * 2);         // Signal<number>, schreibgeschützt, lazy, memoisiert

// LESEN
a();                                       // in TS und im Template: {{ a() }}

// SCHREIBEN
a.set(5);
a.update((v) => v + 1);

// SICHERE FREIGABE
readonly value = this._value.asReadonly();

// OPTIONEN
signal(x, { equal: (p, n) => p.id === n.id, debugName: 'selected' });

// LESEN OHNE ABHÄNGIGKEIT
untracked(a);  untracked(() => a() + b());

// PRÜFUNGEN
isSignal(x);  isWritableSignal(x);

Kap. 03 · 0 von 8 abgeschlossen

Lektion abgeschlossen?

Markiere sie, dann erscheint sie auf deiner Karte: im Inhaltsverzeichnis und auf der Startseite.

Wird automatisch markiert, sobald du die ganze Lektion gelesen hast.

  1. signal() und computed()
  2. effect() — wann ja, wann nein
  3. linkedSignal() — editierbarer abgeleiteter Zustand
  4. resource, rxResource, httpResource
  5. debounced() — verzögerte Signals
  6. Listen: suchen, filtern, sortieren, blättern
  7. Observables von null an
  8. Signals ↔ RxJS
Deine ganze Karte ansehen

Alle 75 Seiten · tippen zum Filtern

  • 01Was ist neu in Angular 21 & 22Alle wichtigen Änderungen in v21 und v22 in Kürze, mit Link zur Seite, die sie jeweils erklärt.Start
  • 01Deine erste App, Schritt für SchrittEine Leseliste, von einer leeren Komponente bis zur fertigen App — Signals, @for, Inputs und Outputs, ein Service und ein Formular, Schritt für Schritt.Start
  • 01Schnelle Entscheidungen„Wohin damit?“, „Signal oder Observable?“, „Shared oder Feature?“ — kurze Antworten auf Alltagsfragen.Start
  • 01Angular-Interviewfragen60 echte Interviewfragen für Junior, Mid und Senior, mit der passenden Antwort, der Nachfrage und den Warnsignalen. Dazu ein Probeinterview.Start
  • 02Standalone & BootstrapWie eine App ohne NgModule startet: bootstrapApplication, app.config.ts, imports in der Komponente.Moderne Grundlagen
  • 02Data Binding & EventsInterpolation, Property- und Attribut-Bindings, Events mit $event und Tastenfiltern und wie [( )] aufgebaut ist — was in das DOM geht und was zurückkommt.Moderne Grundlagen
  • 02Control Flow: @if, @for, @switchDie Block-Syntax, die *ngIf/*ngFor/ngSwitch ersetzt, mit track, @empty und Exhaustive Checks.Moderne Grundlagen
  • 02@let und die neuen Template-AusdrückeLokale Variablen mit @let, Arrow Functions, Spread, Regex, instanceof, Kommentare in Tags.Moderne Grundlagen
  • 02@defer — Lazy Loading in TemplatesSchwere Komponenten nur laden, wenn sie gebraucht werden: Trigger, Prefetch, Placeholder, Loading, Error.Moderne Grundlagen
  • 02Class- & Style-BindingsWarum [class.x] und [style.x] ngClass und ngStyle abgelöst haben (mit automatischer Migration ab v21).Moderne Grundlagen
  • 02Komponenten-Styles & Kapselung:host, die drei Kapselungsmodi, Theming mit CSS-Variablen und warum ::ng-deep der letzte Ausweg ist.Moderne Grundlagen
  • 02Pipes: wann und wiePure vs. Impure Pipes, eigene Pipes und wie du zwischen Pipe, computed() und Methode wählst.Moderne Grundlagen
  • 03signal() und computed()Die reaktiven Grundbausteine: beschreibbarer Zustand, abgeleiteter Zustand, Gleichheit, untracked und Regeln zur Immutability.Signals & Reaktivität
  • 03effect() — wann ja, wann neinMit Signals synchronisierte Seiteneffekte: localStorage, Logging, imperative APIs. Und ihre Stolperfallen.Signals & Reaktivität
  • 03linkedSignal() — editierbarer abgeleiteter ZustandEin Signal, das sich zurücksetzt, wenn sich seine Quelle ändert, das du aber auch manuell setzen kannst.Signals & Reaktivität
  • 03resource, rxResource, httpResourceAsynchrone Daten als Signals: status, value, error, reload, automatischer Abbruch. Stabil seit v22.Signals & Reaktivität
  • 03debounced() — verzögerte SignalsDie „Debounce“-Variante eines Signals, ohne RxJS. Perfekt für die Suche.Signals & Reaktivität
  • 03Listen: suchen, filtern, sortieren, blätternEine Kette von computed-Signals, die nur neu berechnet, was sich geändert hat — mit den Filtern in der URL, damit ein Link dieselbe Ansicht öffnet.Signals & Reaktivität
  • 03Observables von null anWas ein Observable ist, subscribe und unsubscribe, die Operatoren, die du jede Woche brauchst, cold vs. hot — und wann ein Signal reicht.Signals & Reaktivität
  • 03Signals ↔ RxJStoSignal, toObservable, takeUntilDestroyed, outputFromObservable — und wann RxJS weiterhin die richtige Wahl bleibt.Signals & Reaktivität
  • 04input() und output()Inputs als Signals (required, transform, alias) und typisierte Outputs. Daten nach unten, Events nach oben.Komponenten: Kommunikation
  • 04model() — Two-Way-BindingBanana-in-a-Box [( )] mit einer einzigen API. Wann du es nutzt und wann input + output besser ist.Komponenten: Kommunikation
  • 04viewChild & contentChildQueries als Signals: viewChild, viewChildren, contentChild, contentChildren, die Option read.Komponenten: Kommunikation
  • 04Lifecycle & DestroyRefWelche Hooks in der Signals-Ära noch zählen, afterNextRender, DestroyRef und typisiertes ngOnChanges.Komponenten: Kommunikation
  • 04Content Projectionng-content mit select, mehrere Slots, Standardinhalt und die Falle der bedingten Projektion.Komponenten: Kommunikation
  • 04ng-template & ngTemplateOutletTemplates als Werte: Render Props in Angular, typisierter Kontext und Anpassen von Komponenten.Komponenten: Kommunikation
  • 05Smart vs. DumbContainer vs. Presentational: wer den Zustand hält, wer nur anzeigt und wie du die beiden sauber trennst.Komponenten-Design
  • 05Generische Komponenten <T>Eine korrekt typisierte DataTable<T> oder Select<T>, mit Templates für Zellen.Komponenten-Design
  • 05Dynamische KomponentenNgComponentOutlet, createComponent mit inputBinding/outputBinding und ein Dashboard, das aus einer Konfiguration gebaut wird.Komponenten-Design
  • 05Direktiven & Host-KompositionAttribut-Direktiven, die host: {}-Metadaten und die Directive Composition API (hostDirectives).Komponenten-Design
  • 05Eigene Formular-ControlsFormValueControl (Signal Forms) vs. ControlValueAccessor: eine Sternebewertung, in beiden Varianten.Komponenten-Design
  • 05Change DetectionOnPush ist ab v22 der Standard, zone.js entfällt ab v21. Was das Rendering auslöst und wie du dir nicht die Finger verbrennst.Komponenten-Design
  • 06inject() & @Service()Der neue @Service()-Decorator ab v22, inject() vs. Konstruktor und der Injection-Kontext.Dependency Injection
  • 06Provider & die Injector-HierarchieRoot vs. Route vs. Komponente, useClass/useValue/useFactory/useExisting und die Modifier optional/self/skipSelf.Dependency Injection
  • 06InjectionToken & provideX()Typisierte Konfiguration, provideFeature()-Funktionen, makeEnvironmentProviders und Initializer.Dependency Injection
  • 06injectAsync() — Lazy ServicesLade einen schweren Service erst, wenn du ihn brauchst, mit Prefetch im Leerlauf.Dependency Injection
  • 07Ordnerstrukturcore / shared / features, was in welchen Ordner gehört und wie ein Feature von innen aussieht.Architektur der Anwendung
  • 07Shared vs. FeatureWann du eine Komponente nach Shared verschiebst und (vor allem) wann NICHT. Eine konkrete Checkliste.Architektur der Anwendung
  • 07Interfaces & ModelleInline-Interface oder eigene Datei? DTO vs. Domänenmodell, type vs. interface, wohin damit.Architektur der Anwendung
  • 07State Management mit SignalsEinfache Signal-Stores, Fassaden, lokaler vs. globaler Zustand und wann du NgRx brauchst.Architektur der Anwendung
  • 07Styleguide & NamensgebungDie aktuellen offiziellen Konventionen: Dateinamen ohne Suffixe, protected, readonly, Reihenfolge der Member.Architektur der Anwendung
  • 07Barrels, Aliase & Grenzenindex.ts, Pfad-Aliase, die öffentliche API eines Features und Abhängigkeitsregeln, die sich automatisch prüfen lassen.Architektur der Anwendung
  • 07Fehler: @boundary & ErrorHandlerDer neue @boundary-Block ab v22.2, der globale ErrorHandler, HTTP-Fehler und Fehler aus resource.Architektur der Anwendung
  • 08Modernes Routing & Lazy LoadingloadComponent, Child Routes, Parameter als Inputs und Parameter-Vererbung (neuer Standard in v22).Routing
  • 08Guards & ResolvercanActivate, canMatch, canDeactivate und resolve als Funktionen, mit Redirects über UrlTree / RedirectCommand.Routing
  • 09Signal Forms — die GrundlagenFormulare auf Basis von Signals: form(), [formField], schemabasierte Validierung. Stabil seit v22.Formulare
  • 09Signal Forms — fortgeschrittenEigene und feldübergreifende Validierung, async/HTTP mit Debounce, dynamische Listen, disabled/hidden, wiederverwendbare Schemas.Formulare
  • 09Typisierte Reactive FormsTypisierte FormGroup, nonNullable, FormArray — und wie sie neben Signal Forms bestehen.Formulare
  • 10HttpClient, Interceptors & die API-SchichtHttpClient ohne Setup (v21), Fetch als Standard (v22), funktionale Interceptors und eine API-Schicht mit DTO-Mapping.HTTP & Daten
  • 11Performance — eine ChecklisteWas wirklich zählt: OnPush + Signals, track, @defer, Lazy Routes, Bilder, Bundles und Hydration.Qualität & Performance
  • 11Testen mit VitestVitest ist ab v21 der Standard-Runner. TestBed, Komponenten mit Signals, Services, HTTP und Harnesses.Qualität & Performance
  • 11DevTools: ein Blick in deine AppChrome DevTools und Angular DevTools Schritt für Schritt: was jedes Panel zeigt, mit Übungen, die auf dieser Website funktionieren.Qualität & Performance
  • 11Angular AriaHeadless, barrierefreie Komponenten, die du nach Belieben stylst: Tabs, Accordion, Menü, Listbox...Qualität & Performance
  • 12SSR, Prerendering & Render ModesWann auf dem Server gerendert wird, wann beim Build und wann nur im Browser: RenderMode pro Route, app.routes.server.ts und die echten Kosten.SSR & Hydration
  • 12Hydration: Event Replay & inkrementellWie der Browser das Server-HTML übernimmt, ohne es neu zu rendern: vollständige Hydration, Event Replay, @defer (hydrate on …) und Mismatch-Fehler.SSR & Hydration
  • 12Servertauglicher Codewindow gibt es auf dem Server nicht: PLATFORM_ID, afterNextRender, DOCUMENT, TransferState, der HTTP-Cache und PendingTasks.SSR & Hydration
  • 13Micro FrontendsWann es sich lohnt, eine App in mehrere Deployments aufzuteilen und wann es nur Komplexität ist: Native Federation, Module Federation, iframes, Web Components.Architektur im großen Maßstab
  • 13Web Components mit Angular ElementscreateCustomElement: eine Angular-Komponente, die überall als HTML-Tag nutzbar ist, plus Kommunikation zwischen Apps über Events und BroadcastChannel.Architektur im großen Maßstab
  • 13Monorepo, Bibliotheken & GrenzenEin Workspace mit mehreren Apps und Bibliotheken: ng generate library, Nx, Secondary Entry Points, Publishing und Abhängigkeitsregeln.Architektur im großen Maßstab
  • 13Hexagonale Architektur (Ports & Adapters)Eine Domäne ohne Angular, Ports als abstrakte Klassen und austauschbare Adapter: HTTP, localStorage oder In-Memory, ohne die UI anzufassen.Architektur im großen Maßstab
  • 14Signals unter der HaubeDer reaktive Graph: Producer und Consumer, Push-Pull, warum computed lazy und glitch-frei ist, das Diamond-Problem und wann Effects laufen.Fortgeschrittene Reaktivität
  • 14Fortgeschrittenes RxJS: Operatoren höherer OrdnungswitchMap, mergeMap, concatMap und exhaustMap an einem Live-Diagramm, dazu Retry mit Backoff, shareReplay und wie du Leaks vermeidest.Fortgeschrittene Reaktivität
  • 14NgRx SignalStoreState Management im großen Stil auf Signals: withState, withComputed, withMethods, rxMethod, Entities und Hooks — und wann ein einfacher Store reicht.Fortgeschrittene Reaktivität
  • 14Zustandsautomaten mit SignalsKeine unmöglichen Zustände mehr: ein typisierter Automat auf Signals, mit Übergängen, Guards und einem Live-Zustandsdiagramm.Fortgeschrittene Reaktivität
  • 15WebSockets: Echtzeit, die das Netz überstehtEin typisierter Socket als Signals: Reconnect mit Backoff und Jitter, Heartbeat, ein Postausgang im Offline-Modus und SSR-Sicherheit.Echtzeit & offline
  • 15Optimistische Updates & RollbackEine sofortige UI, die ehrlich bleibt: Snapshot und Rollback, Antworten in falscher Reihenfolge, Idempotenzschlüssel.Echtzeit & offline
  • 15Offline-first: Service Worker & CachingDer Angular Service Worker: Caching-Strategien, Update-Hinweise und ein Postausgang für Änderungen, die offline entstehen.Echtzeit & offline
  • 16Web WorkersSchwere Berechnungen, ohne die UI zu blockieren: ein echter Worker in der Seite, Message Passing und wann es sich nicht lohnt.Fortgeschrittene UI & Performance
  • 16Riesige Listen: Virtual Scroll100.000 Zeilen ohne Ruckeln: CDK Virtual Scroll, itemSize, trackBy und die Alternativen (Paginierung, Infinite Scroll).Fortgeschrittene UI & Performance
  • 16Moderne Animationen & View Transitionsanimate.enter und animate.leave statt des veralteten @angular/animations, CSS-Transitions und View Transitions bei der Navigation.Fortgeschrittene UI & Performance
  • 16Memory Leaks finden und behebenSubscriptions, Timer und Listener, die ihre Komponente überleben – wie du sie in den DevTools findest und schließt.Fortgeschrittene UI & Performance
  • 17Sicherheit: XSS, Sanitizing & CSPWas Angular automatisch gegen XSS tut, wann bypassSecurityTrust gefährlich wird, dazu CSP mit Nonce, Trusted Types und XSRF.Sicherheit & Globalisierung
  • 17Authentifizierung: Tokens & RefreshEin Interceptor, der das Token anhängt, bei 401 einmal erneuert und die wartenden Requests wiederholt — dazu, wo du das Token aufbewahrst.Sicherheit & Globalisierung
  • 17OAuth 2.1 & OpenID Connect mit PKCEDer Authorization-Code-Flow mit PKCE Schritt für Schritt: Verifier und Challenge, State und Nonce, das ID-Token und warum ein BFF sicherer ist.Sicherheit & Globalisierung
  • 17Internationalisierung (i18n)$localize, das i18n-Attribut, ICU plural/select, ein Build pro Sprache vs. Übersetzungen zur Laufzeit und Formatierung nach Locale.Sicherheit & Globalisierung