material(ngrx): State Management mit NgRx – Serie (Teil 1–3) + Beispiel-Apps#105
Draft
JohannesHoppe wants to merge 24 commits into
Draft
material(ngrx): State Management mit NgRx – Serie (Teil 1–3) + Beispiel-Apps#105JohannesHoppe wants to merge 24 commits into
JohannesHoppe wants to merge 24 commits into
Conversation
…Stub
- Teil 2 aus dem rohen Tool-Dump zu sauberem Markdown aufbereitet:
- alle LaTeX-Artefakte entfernt (\lstinputlisting, \footnote, \mbox,
\file, \begin{...}, \autoref, \index, Layout-Makros usw.)
- alle Code-Listings aus den Buch-Snippets eingesetzt (vorher fehlten sie
komplett, es standen nur die \lstinputlisting-Direktiven da)
- versehentlich mitkopierte Fremdkapitel (Prettier, EAP, Raetsel,
Changelog, Vorwort) entfernt
- Frontmatter, Serien-Header (3-teilig) und [[toc]] ergaenzt
- DevTools-Screenshots eingebunden, 4 Diagramme als TODO markiert
- Shortlinks aufgeloest, gerade Anfuehrungszeichen, z. B. statt z.\,B.
- Teil 3 (SignalStore) als Stub mit Frontmatter und Platzhalter angelegt
- redux-flow-simple, selectors-gap, ngrx-flow-full, facade - aus den Buch-PDFs per 'pdftocairo -svg' nach SVG konvertiert (Vektor, kein Rasterbild), kein yEd noetig - TODO-Platzhalter durch echte Bild-Einbindungen mit beschreibendem Alt-Text ersetzt
- selectors-gap, ngrx-flow-full und facade: Label 'select()' bzw. 'store.select(...)' durch 'selectSignal()' ersetzt - alte (als Vektor-Pfad vorliegende) Beschriftung in Hintergrundfarbe ueberdeckt und durch echten, editierbaren <text> ersetzt - Bild-Alt-Texte/Titel entsprechend angepasst Hinweis: Der Fliesstext von Teil 2 nennt weiterhin store.select() (buchtreuer Port) - die Angleichung an selectSignal() erfolgt in der Modernisierung (Phase 2).
… TypeScript-Querverweis - A1: Hinweis-Box ergaenzt (Historie der Nachrichten wird in der Praxis nicht gespeichert) - war im Buch eine Fussnote, ging beim Port verloren - C: Verweis auf Spread-/Rest-Syntax als Link auf /material/typescript gesetzt; uebrige rein buchinterne Querverweise bleiben bewusst weg - lastModified aktualisiert
Gegen die offizielle NgRx-Doku (ngrx.io, v21/v22) und das Schematic im Repo verifiziert: - Standalone statt NgModule: provideStore/provideState/provideEffects/ provideStoreDevtools in app.config.ts bzw. Route-providers; NgModule-Weg komplett entfernt - Store-Lesen mit store.selectSignal() (Signal) statt store.select() (Observable); Templates mit @if/@for statt *ngIf/*ngFor, keine AsyncPipe - Effects mit inject()-Feldern; funktionale Effects als gleichwertige Variante ergaenzt (entspricht dem aktuellen Effect-Blueprint, PR #5155) - useDefineForClassFields-Abschnitt entfernt (obsolet, Issue #3654) - concatLatestFrom aus @ngrx/operators (seit v18 umgezogen) - createFeature als moderne Reducer/Selektor-Buendelung ergaenzt - @ngrx/component als Maintenance-Modus eingeordnet - Versionsnote auf Angular 22; durchgaengig wir-Form statt Sie-Form
- '--defaults' aus 'ng add @ngrx/store' und 'ng g feature' entfernt (ist kein NgRx-Schematic-Flag) - concatLatestFrom-Historie praezisiert (in @ngrx/operators seit v18, in @ngrx/effects seit v17 deprecated)
…fiziert Komplett neuer Artikel (war nicht im Buch). Struktur: architektonischer Unterschied zum Global Store / Vorstellung / Vergleich / Fazit. - gesamte @ngrx/signals-Doku (17 Seiten) per Headless-Chrome in den Context geholt, jede API gegen ngrx.io verifiziert (kein Raten) - signalStore/withState/withComputed/withMethods/withHooks, patchState, rxMethod, withEntities, signalStoreFeature, lokal vs. providedIn:'root' - durchgehendes BookMonkey-Beispiel analog zu Teil 2 (Buchliste + Ladeindikator) - Vergleichstabelle Global Store vs. SignalStore, Entscheidungshilfe im Fazit - ehrlich eingeordnet: keine offizielle Redux-DevTools-Anbindung, Events-Plugin (seit 19.2) fuer Flux-Stil, ersetzt @ngrx/component-store - adversarialer Review-Agent: keine erfundene API, keine falschen Signaturen; protectedState-Aussage praezisiert
Form-neutrale Korrekturen aus dem kritischen Lektorat: - T1: Em-Dash in Zitat-Attribution -> Halbgeviertstrich; 'weiter gehen' -> 'weiter treiben'; toter Vorwaerts-Verweis -> Link auf Teil 2; shareReplay-Formulierung praezisiert - T2: 'Lassen Sie uns' -> 'Fassen wir' (letzte Sie-Form); fehlende Leerzeile vor Ueberschrift; Effect-Fehlerfall klarer; root- vs. feature-provideEffects erklaert - T3: 'haengt im einen' -> korrekt; Kongruenz 'waren'; Kasus 'einem Lade-Status'; Wiederverwendungs-Aussage entschaerft; withEntities als Variante gekennzeichnet; component-store-Redundanz entfernt; Wortwdh. Anrede-Umstellung (du) noch offen (Rueckfrage).
…n-Konsistenz) - 'Bitte beachten Sie' -> 'Wir muessen beachten' - 'Welches der Frameworks Sie ... Ihren Favoriten' -> wir/unseren, 'Ihnen empfehlen' -> 'empfehlen' - Pronomen 'sie' (Methode/Funktion/Frameworks) bleiben korrekt - lastModified T1+T2 auf 2026-06-13 Alle drei Teile jetzt durchgaengig wir-Form (konsistent mit den uebrigen Material-Artikeln).
…n C) Beide Teile zeigen jetzt ein vollstaendiges, baufaehiges Feature (Laden + Anlegen/Aendern/Loeschen + Fehler-State + UI-Anzeige), gegen ngrx.io verifiziert (adversarialer Review: keine Fehler). Teil 3 (SignalStore), neu strukturiert zu durchgehendem Beispiel: - error-Feld im State; patchState-Updater-Funktion fuer immutables Array-Update (add/update/delete) gezeigt - Schreib-Methoden via rxMethod + concatMap + tapResponse + Fehler-State - EIN konsolidierter Komplett-Store (Laden + CRUD + computed + withHooks) - Komponente mit Aktionen (Loeschen-Button) + Fehleranzeige im Template - Route-providers fuer lazy Feature ergaenzt - withEntities-Variante zeigt addEntity/updateEntity/removeEntity als Automatisierung der manuellen Updates (Phantom-APIs behoben) - Test mit gemocktem BookStoreService Teil 2 (Global Store), neuer Abschnitt 'Buecher anlegen, aendern, loeschen': - error-Feld im State + loadBooksFailure setzt error - Create/Update/Delete-Actions-Trios, Effects mit concatMap (statt switchMap) fuer Schreibvorgaenge, immutable Reducer-Updates - Mehrfach-on() fuer die Fehlerfaelle, selectBooksError + selectSignal - Komponente mit dispatch + Fehleranzeige - macht den Boilerplate-Kontrast zu Teil 3 explizit
… & 3 Zwei echte Angular-21-Apps (Vitest, zoneless) in den jeweiligen Artikel-Verzeichnissen unter demo/ — beweisen, dass der Artikel-Code laeuft. NgRx 21 (latest; NgRx 22 ist noch nicht auf npm). material/ngrx-global-store/demo (@ngrx/store + @ngrx/effects): - Book-Modell, In-Memory BookStoreService, Actions/Reducer/Selektoren/ Effects mit Laden + CRUD + Fehler-State (Code wie im Artikel) - 16 Vitest-Tests gruen: Reducer (alle CRUD-Transitions), Selektoren, Effects (provideMockActions, switchMap/concatMap), App (provideMockStore) - ng build erfolgreich material/ngrx-signal-store/demo (@ngrx/signals + @ngrx/operators): - signalStore mit withState/withComputed/withMethods/rxMethod/withHooks, Laden + CRUD + Fehler-State (Code wie im Artikel) - 7 Vitest-Tests gruen: Store (Laden, add/update/delete, Fehler, clearError) + App-Komponente - ng build erfolgreich Beim Bauen entdeckt & gefixt: Teil 3 nutzte store.clearError() im Template, der konsolidierte Store definierte es nicht -> ergaenzt (in App und Artikel).
…egacy-peer-deps)
- ng update @angular/{cli,core}@22 in beiden Demos (Signal Store + Global Store)
- NgRx bleibt 21.1.1: laeuft unter Angular 22; .npmrc mit legacy-peer-deps=true
sorgt fuer reibungsloses "npm install" (NgRx-21-Peer-Range ist noch ^21.0.0)
- ChangeDetectionStrategy.Eager-Migration zurueckgenommen, damit die Demo
deckungsgleich zum Artikel bleibt; tsconfig-Diagnostics der Migration uebernommen
- Beweis auf Angular 22 (frischer npm install): Signal Store 7/7, Global Store 16/16
Vitest gruen, beide bauen (124 kB / 146 kB)
- Demo-READMEs auf "Angular 22" aktualisiert inkl. Hinweis zur Peer-Range
Faktische Fehler:
- Buchauflage korrigiert: "(4. Auflage)" -> "(1. Auflage)" in allen drei Teilen
- NgRx richtig aufgeloest: "Reactive State for Angular" statt "Reactive Extensions ..."
- Entity-Reducer-Bug: createBookSuccess + action.book (war createBook/action.data)
Korrektheit & Konsistenz (Artikel an bewiesene Demos angeglichen):
- Ehrliche Fehler-Typisierung: unknown + toMessage()-Helfer statt {message:string}
- Schreibvorgaenge setzen alte Fehlermeldung zurueck (Reducer/SignalStore + Artikel)
- Teil-2-State-Illustration und Test-Stubs um error-Feld ergaenzt
- Phantom-Import ./test-helper raus -> inline-Helfer (b()/book()), String-ISBNs
- "Propertys" -> "Properties"; Teil 1 "Kapitel" -> "Artikel"; scan()-Aussage entschaerft
Demos: vollstaendiges CRUD jetzt sichtbar
- Anlege-Formular + "Bewertung +1" (update) + Loeschen verdrahtet; rating wird genutzt
- OnPush ergaenzt; leere app.css entfernt; .error/.add-form-Styles; app.config aufgeraeumt
- Global-Demo: ungenutztes @ngrx/operators entfernt
- In-Memory-Service wirft bei doppelter ISBN -> Fehleranzeige ohne Server ausloesbar
Tests deutlich erweitert (Beweis auf Angular 22 / NgRx 21):
- Global: updateBook$-Effect + alle Failure-Pfade + Komponententest (16 -> 27)
- Signal: Write-Failure, loading-Transition, error-reset, Komponententest (7 -> 12)
Hygiene & Didaktik:
- .vscode/mcp.json (npx-basiert) aus der Versionierung entfernt
- Teil 3: async/Promise-Aussage entschaerft, HttpClient-Service-Hinweis, Test ohne
doppeltes loadBooks() (onInit), store.select()-Erklaerung in Effects (Teil 2)
- Demo-READMEs: CRUD-Beschreibung, Testumfang, Hinweis auf abgeflachte Struktur
- lastModified der Artikel auf 2026-06-14
Beweis: Global 27/27, Signal 12/12 Vitest gruen; beide bauen (148 kB / 126 kB).
…ests, Politur Korrektheit/Ehrlichkeit: - Versionshinweise (Teil 2 + 3) richtiggestellt: Angular 22 + NgRx 21 laufen via legacy-peer-deps zusammen (NgRx 22 noch nicht released) – keine "passende"/ Major-Schema-Aussage mehr - Minko-Gechev-Zitat (nicht mehr belegbar) aus Teil 1 entfernt Demo-Parität & exemplarischer Code: - clearError nun auch im Global Store (Action + Reducer + OK-Button) -> beide Demos und beide Artikel dismissen Fehler einheitlich - addBook nimmt die Input-Elemente entgegen, leert die Felder selbst (statt Mehrfach-Statement im Template); aria-label an den Eingabefeldern - toMessage-Kommentar präzisiert (HttpErrorResponse ist kein instanceof Error) - ungenutzte Deps @angular/forms und @angular/router aus beiden Demos entfernt Tests erweitert (Beweis der neuen UI-Logik): - Global 31, Signal 16 (vorher 27/12): add-on-click, Leer-Guard, rateUp-Clamp@5, clearError-Klick, clearError-Reducer Konsistenz/Politur: - Demo-READMEs: Hinweis auf flache CLI-Namen vs. BookMonkey-Konvention - Teil-2-Testhinweis entschärft (vitest-marbles nicht im Demo enthalten) - Teil-3-Inkrement: Ternär-Klammern + Testdaten (Title) an Demo angeglichen - "nach dem Dispatch" -> "nach dem Anlegen" im SignalStore-Text Beweis: Global 31/31, Signal 16/16 Vitest gruen; beide bauen (148 kB / 126 kB).
…e entfernt
Der Angular-Style-Guide hat die Typ-Suffixe abgeschafft (Datei- UND Klassennamen):
- Komponenten in den Artikeln: BookListComponent -> BookList,
book-list.component.{ts,html,spec.ts} -> book-list.{ts,html,spec.ts}
(die Demos waren hier bereits flach)
- Datenservice überall: book-store.service.ts -> book-api.ts, Klasse
BookStoreService -> BookApi (Methoden getAll/create/update/remove unverändert).
Der kurze, suffixfreie Name vermeidet zudem die Kollision mit dem
NgRx-SignalStore BookStore in Teil 3.
- Artikel, beide Demos und alle Specs angeglichen; Demo-READMEs aktualisiert
(verbleibende Unterschiede: Feature-Ordner books/ vs. flach, Präfix bm- vs. app-).
Beweis: Global 31/31, Signal 16/16 Vitest gruen; beide bauen (148 kB / 126 kB).
- angular.json prefix app -> bm in beiden Demos - Selektoren: app-root -> bm-root, app-book-list -> bm-book-list - Templates/index.html entsprechend; Demos damit deckungsgleich zu den Artikeln - Demo-READMEs: Präfix-Unterschied entfernt (nur noch Ordnerstruktur differiert) Beweis: Global 31/31, Signal 16/16 Vitest gruen; beide bauen (148 kB / 126 kB).
- Alle Nennungen des Projektnamens in den drei Teilen und beiden Demo-READMEs von "BookMonkey" auf "BookManager" umgestellt (Buch-Umbenennung 1. Auflage). - Der Selektor-/CLI-Präfix bm- bleibt: "bm" passt weiterhin (BookManager). - errata-3a/4a bewusst unverändert: Sie verweisen auf die historischen Projekte und veröffentlichte Artefakte (GitHub book-monkey4, npm book-monkey5-styles) und dürfen nicht umbenannt werden.
…er Pflege)
- Feste "Angular 22 / NgRx 21"-Nennungen aus den Artikel-Hinweisen entfernt;
übrig bleibt die dauerhaft gültige Aussage zu Standalone/Signals/inject().
- Demo-READMEs: Stack ohne feste Nummern (Versionen stehen in package.json);
der legacy-peer-deps-Hinweis ist jetzt allgemein formuliert (gilt für jeden
Angular-Major-Wechsel, nicht nur 21↔22) – muss bei NgRx-Releases nicht mehr
angefasst werden.
- Historische Hinweise ("seit NgRx 18/19.2") bleiben, sie sind dauerhaft korrekt.
- Konkrete Versionen leben nur noch in package.json (per ng update pflegbar).
- Die "Hinweis zur Version"-Blöcke in Teil 2 und Teil 3 komplett gestrichen. - Demo-READMEs: legacy-peer-deps-Hinweis entfernt, Versions-Zusatz an der Paketzeile entfernt. Die .npmrc bleibt liegen, npm install läuft also weiterhin ohne Zutun durch – nur eben ohne erklärenden Kasten. - "Projektstruktur"-Notiz bleibt (versionsunabhängig). Damit enthalten die Texte keinerlei versionsgebundene Meta-Hinweise mehr.
- Datenservice: In-Memory raus -> echter HttpClient `BookStore` (@service()) gegen die oeffentliche API api1.angular-buch.com (getAll/create/remove), provideHttpClient in app.config; Service-Tests via HttpTestingController. - Volles Buch-Modell (isbn/title/subtitle?/authors/description/imageUrl/ createdAt); kein rating mehr, kein update (hat das Buch ebenfalls nicht). - Favoriten als reiner Client-State (likeBook/clearLikedBooks) -> Kontrast Server-State (Effects/rxMethod) vs. lokaler State ohne Seiteneffekt. - Komponenten im Buch-Stil: praesentationale book-card (like/remove-Output) + smarte books-overview (Favoriten- + Buecher-Sektion). - Naming: Datenservice BookStore (buchidentisch); global = injizierter Store, signal = BookSignalStore. Prefix bm- -> app- (wie das Buch). Beweis: Global 37/37, Signal 21/21 Vitest gruen; beide bauen (174/152 kB).
…Code) Alle Code-Schnipsel jetzt deckungsgleich mit den bewiesenen Demo-Apps: - Datenservice BookStore (@service(), HttpClient gegen api1.angular-buch.com), kein In-Memory; volles Buch-Modell ohne rating; provideHttpClient. - update/PUT entfernt (hat das Buch nicht): CRUD-Abschnitt = "anlegen und loeschen". - NEU: Favoriten als reiner Client-State (likeBook/clearLikedBooks ohne Effect bzw. ohne rxMethod) - didaktischer Kontrast Server-State vs. lokaler State. - "store"-Mehrdeutigkeit aufgeloest: Datenservice = BookStore (buchidentisch), global = injizierter Store, signal = BookSignalStore. - Komponenten im Buch-Stil (book-card/books-overview), Prefix app-. - Fehler ueber HttpErrorResponse/toMessage; Tests mit HttpTestingController. - Teil 1: BookApi-Nennung -> BookStore. Verifiziert: 0 Alt-Residuen, Fences balanciert, Code = Demo (Agent-Gegenpruefung), wir-Form, keine Versions-Pins.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Dreiteilige Artikelserie State Management mit NgRx plus zwei lauffähige Beispiel-Apps, portiert auf das aktuelle Buch (BookManager).
BookStore-HttpClient gegenapi1.angular-buch.com, Favoriten als Client-StateNoch nicht notwendig zu reviewen, Teil 3 ist 100% AI. Da gehe ich nochmal rüber