Eine Angular-Anwendung ist eine einzige HTML-Seite, und der Router zeigt je nach Adresse eine andere Komponente an. Für Sie als Autorin oder Autor der API ist das dasselbe Muster wie das Routing in ASP.NET Core (K2 2.3.2): Eine Tabelle ordnet Adressen Handlern zu, Parameter kommen aus dem Pfad. Die Lektion legt die Seiten der Kladde an (Kontakte, Kontakt, Termine, Buchung, 404) mit Lazy Loading, Titel, Fokus nach dem Wechsel und Tests. Die Daten kommen in 0202 aus der API.
Wie bisher: Projekt web/kladde-angular, Präfix kl, Ordner src/app/{kontakte,termine,buchung,shared,core} (0101). Die Vorlagen stehen hier der Kürze wegen im Code der Komponente; Ihre Dateien haben templateUrl und
styleUrl (0102).
Stand der Prüfung. Das Beispiel stammt aus einem Wegwerfprojekt außerhalb des Repositorys (Node 24.22.3, Angular 22.2.6, TypeScript 6.0.3, Vitest 5.1.0). Gelaufen sind
ng build(Exit-Code 0) undng test --no-watchmit den Routen-Tests dieser Lektion (5 Tests inapp.spec.ts; der Endstand nach 0204 besteht 32 Tests in 7 Dateien, Exit-Code 0). Ein Test wurde zur Probe gebrochen (ZeilecanMatchentfernt) und wurde rot. Nicht ausgeführt: der Dev-Server im Browser, jede Handprobe mit Tastatur und Screenreader, die Navigation gegen eine laufende API; die Tests laufen in jsdom. Ob Angular für den Fokus nach der Navigation selbst etwas anbietet, haben wir nicht gelesen: offen. Die Aussagen zu Guards und Resolvern stammen von den Seiten der Angular-Dokumentation, am Schreibtag gelesen.
Die Tabelle der Routen
Der Router wird einmal in app.config.ts angemeldet. provideRouter bekommt die Tabelle routes und, für diese Lektion, die Funktion withComponentInputBinding(); wozu sie dient, zeigt der Abschnitt über Pfadparameter.
src/app/app.config.ts (Auszug):
provideRouter(routes, withComponentInputBinding()),
Eine Route ist ein Objekt mit einem path und dem, was dort angezeigt wird. Der Router prüft die Einträge in der Reihenfolge der Datei und nimmt den ersten, der passt. Das ist dieselbe Regel, nach der Sie in einer API
eine Route mit Platzhalter hinter die festen Routen setzen. Die Tabelle der Kladde:
src/app/app.routes.ts:
import { Routes } from '@angular/router';
import { nurGuid } from './core/routing/nur-guid';
import { kontaktLaden } from './kontakte/kontakt-laden';
export const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'kontakte' },
{
path: 'kontakte',
title: 'Kontakte',
loadComponent: () => import('./kontakte/kontakt-liste').then((m) => m.KontaktListe),
},
{
path: 'kontakte/:id',
title: 'Kontakt',
canMatch: [nurGuid],
resolve: { kontakt: kontaktLaden },
loadComponent: () => import('./kontakte/kontakt-detail').then((m) => m.KontaktDetail),
},
{
path: 'termine',
title: 'Termine',
loadComponent: () => import('./termine/termine-seite').then((m) => m.TermineSeite),
},
{
path: 'buchung',
title: 'Termin buchen',
loadComponent: () => import('./buchung/buchung-seite').then((m) => m.BuchungSeite),
},
{
path: '**',
title: 'Seite nicht gefunden',
loadComponent: () => import('./shared/nicht-gefunden').then((m) => m.NichtGefunden),
},
];
Drei Dinge fallen auf. Erstens pathMatch: 'full' bei der Weiterleitung von der Wurzel: Ohne es träfe der leere Pfad jede Adresse als Anfang. Zweitens title: Der Router setzt den Seitentitel; für Screenreader und
Verlauf ist das die erste Auskunft, wo man ist. Drittens '**' ganz unten: die Route für alles, was keine andere trifft, die 404-Seite der Anwendung. Sie sagt nichts über den Statuscode: Der Server liefert für jede Adresse die index.html aus (0403).
Lazy Loading mit loadComponent
loadComponent bekommt eine Funktion, die die Datei der Komponente per import() nachlädt, erst wenn die Route gebraucht wird. Der Build teilt den Code dafür in eigene Dateien: Das ng build des Projekts listete unter „Lazy chunk files“ fünf Teile (kontakt-liste, termine-seite, kontakt-detail, nicht-gefunden,
buchung-seite) mit 0,3 bis 2,1 kB. Eine kleine Büro-Anwendung gewinnt damit wenig; der Nutzen wächst mit ihr, und er kostet hier nichts.