Dieser Kurs setzt ein Angular-Front-End vor die Kladde-API aus K2. Sie kennen C#, ASP.NET Core, Web-APIs, Anmeldung mit Entra ID und Tests (K2 2.2, 2.3, 2.6, 2.7, 2.12) und lernen Angular von Null, mit dem Blick dessen, der die API geschrieben hat. Diese Lektion legt das Projekt web/kladde-angular an, zeigt, was die CLI erzeugt, hängt den Dev-Server an die API und klärt eine Frage für den ganzen Kurs: Muss strict in der tsconfig.json stehen? TypeScript selbst lehrt der Kurs nicht (K2 2.2).

Stand der Prüfung. Ausgeführt wurde mit Node 24.22.3 und Angular CLI 22.2.7: ng new mit --skip-install (in zwei Fassungen), ng generate component und ng generate service, ng build (Exit-Code 0, bei absichtlichen Fehlern 1), ng test --no-watch mit Vitest (Exit-Code 0, 2 Tests, im Projekt von 0102) und ein kurzer ng serve mit Proxy gegen einen kleinen HTTPS-Testserver auf Port 7180 (curl: 200, ohne secure: false 502). Die Pakete installierte ein Referenzprojekt mit byte-gleicher package.json. Nicht ausgeführt: die Anlage mit Paketinstallation in einem Zug, das Schlüsselpaar von dotnet dev-certs, die echte Kladde-API, ein Browser, der Test aus Übung 1 nach Ihrer Änderung. Fakten zu Fassungen stammen von angular.dev (gelesen am Schreibtag); was nicht gelesen wurde, steht als offen da.

Was Angular für Sie ist

Angular ist ein Framework mit Vorgaben: Es bringt Werkzeug (CLI, Build, Test), eine feste Projektform, Abhängigkeitsinjektion, Router, HTTP-Client und Formulare mit. Für eine .NET-Entwicklerin liest sich das vertraut: Dienste kommen per inject() an, app.config.ts ist das Gegenstück zu Program.cs, und die CLI erzeugt Dateien wie dotnet new. Der Preis: Sie lernen die Vorgaben, bevor Sie schnell sind. Es lohnt sich bei einer größeren Oberfläche mit mehreren Menschen; für eine kleine Seite genügt oft Blazor (K2 2.5).

Ein Angular-Programm besteht am Ende aus statischen Dateien (HTML, JavaScript, CSS), die im Browser laufen und die API per HTTP aufrufen. Alles im Bundle ist öffentlich; ein Geheimnis gehört nie hinein.

Fassungen und Unterstützungsfenster

Die Seite der Releases (angular.dev/reference/releases) nennt am Lesetag die Hauptfassung 22 (@angular/core 22.2.6; die Dokumentation trägt „Built at v22.2.6“). Je Jahr kommt ein Hauptsprung, jede Fassung ist 12 Monate aktiv und 12 Monate in der Langzeitpflege (LTS). Fassung 21 ist in der Langzeitpflege, die von 20 endet bald; die Daten stehen auf der Seite. Die Seite der Versionen (angular.dev/reference/versions) nennt für Angular 22 Node ^22.22.3 || ^24.15.0 || ^26.0.0 und TypeScript >=6.0.0 <6.1.0.

Der Kurs nimmt Node Linie 24. Prüfen Sie die Fassung vor jeder Anlage (die Maschine des Schreibens hatte als Standard 22.12.0, dafür meldet npm Warnungen; alle Läufe hier nutzten 24.22.3):

PowerShell
node --version
npm --version

Nicht verwechseln: K2 baut die API-Seite mit TypeScript 7 über NuGet, ein anderes Projekt. npm ist hier nur das Werkzeug von Angular.

Die CLI und das Projekt anlegen

Die CLI heißt ng: ng new legt an, ng serve startet den Dev-Server, ng build baut, ng generate erzeugt Dateien, ng test testet. Aus ng new --help (22.2.7) lesen wir die Optionen, die für uns zählen: --routing, --style=scss (unsere Regel), --prefix (Vorsilbe der Selektoren, Standard app), --strict (Standard an), --zoneless, --test-runner (vitest Standard, karma), --file-name-style-guide (2025 Standard mit app.ts, 2016 mit app.component.ts), --skip-git, --skip-install und --ai-config (none lässt Dateien für KI-Werkzeuge weg). Im Ordner web des Kladde-Repositorys (dort gibt es schon ein Git-Repository):

PowerShell
npx @angular/cli@22 new kladde-angular --routing --style=scss --prefix=kl --skip-git --ai-config=none

Beim Schreiben lief derselbe Befehl mit Fassung 22.2.7 und zusätzlich --skip-install; er erzeugte (ohne README.md, .editorconfig, .gitignore, .vscode/*, app.spec.ts, app.scss):

CREATE kladde-angular/.prettierrc (173 bytes)
CREATE kladde-angular/angular.json (2134 bytes)
CREATE kladde-angular/package.json (789 bytes)
CREATE kladde-angular/tsconfig.json (939 bytes)
CREATE kladde-angular/tsconfig.app.json (412 bytes)
CREATE kladde-angular/tsconfig.spec.json (423 bytes)
CREATE kladde-angular/src/main.ts (228 bytes)
CREATE kladde-angular/src/index.html (310 bytes)
CREATE kladde-angular/src/styles.scss (81 bytes)
CREATE kladde-angular/src/app/app.ts (309 bytes)
CREATE kladde-angular/src/app/app.html (20488 bytes)
CREATE kladde-angular/src/app/app.config.ts (322 bytes)
CREATE kladde-angular/src/app/app.routes.ts (80 bytes)
CREATE kladde-angular/public/favicon.ico (15086 bytes)

Die Namen ohne .component folgen der Seite „Style Guide“: App liegt in app.ts, app.html, app.scss, ohne Suffix.

  • src/main.ts startet mit bootstrapApplication(App, appConfig).
  • src/app/app.config.ts ist die Konfiguration beim Start, eine Liste von providers (die Vorlage setzt provideBrowserGlobalErrorListeners() und provideRouter(routes)). Hier kommen provideHttpClient(...) (0202) und die Anmeldung (0301) dazu.
  • src/app/app.ts ist die Wurzelkomponente (imports: [RouterOutlet], selector: 'kl-root'); app.html eine Platzhalterseite von 20 KB, die Sie in der Übung ersetzen; app.routes.ts hält die Routen (leer; 0201).
  • angular.json beschreibt die Ziele build, serve, test. Der Build nutzt @angular/build mit dem Builder application; inlineStyleLanguage steht auf scss.
  • tsconfig.json, tsconfig.app.json (schließt *.spec.ts aus) und tsconfig.spec.json (vitest/globals) konfigurieren TypeScript.
  • package.json nennt Skripte und Abhängigkeiten, ohne zone.js (unten); package-lock.json gehört ins Repository, mit ihr holt npm ci überall dieselben Pakete.
  • public/ wird unverändert ausgeliefert; src/index.html ist die eine Seite mit <kl-root></kl-root>. Dort ändern Sie sofort <html lang="en"> zu lang="de" (Screenreader wählen danach die Sprache) und den <title> auf Kladde.

Standardläufer der Tests ist Vitest; Prüfläufe: ng test --no-watch, Exit-Code lesen (0401).

Strict: gehört es ausdrücklich in die tsconfig?

Unsere Regel: TypeScript ist strict. Die erzeugte tsconfig.json enthält aber kein "strict": true; unter compilerOptions stehen noImplicitOverride, noPropertyAccessFromIndexSignature, noImplicitReturns und noFallthroughCasesInSwitch, unter angularCompilerOptions strictInjectionParameters und strictInputAccessModifiers. Ist das Projekt dann nicht strict?

Der Versuch, in einer Kopie mit TypeScript 6.0.3: App bekam eine Methode mit text.length bei text: string | undefined und ein Feld leer: string = null. Vier Läufe von ng build:

Lauf tsconfig.json Ergebnis
1 wie erzeugt, ohne strict Exit-Code 1: TS18048: 'text' is possibly 'undefined' und TS2322: Type 'null' is not assignable to type 'string'
2 mit "strict": true Exit-Code 1, dieselben zwei Fehler
3 mit "strict": false Exit-Code 0, derselbe Code
4 wie erzeugt, Template mit [anzahl]="'drei'" für ein input.required<number>() Exit-Code 1: TS2322: Type 'string' is not assignable to type 'number'

Ergebnis: Mit dieser Vorlage und TypeScript 6.0.3 ist die strenge Prüfung auch ohne den Eintrag an, bis "strict": false sie abschaltet. Die Seite „tsconfig“ von typescriptlang.org nennt für strict den Standard true (gelesen); zu einer Änderung in 6.0 sagt sie nichts, die Beobachtung gilt für 6.0.3. ng new --no-strict schreibt in der erzeugten Datei "strict": false und "strictTemplates": false.

Entscheidung für den Kurs: Wir schreiben "strict": true nicht zusätzlich hinein; es ändert das Ergebnis nicht. Stattdessen gilt die Probe aus Übung 1 in jedem Projekt dieses Kurses: In den tsconfig-Dateien steht kein "strict": false, und ein absichtlicher Fehler bricht den Build. Wer ein Projekt mit --no-strict erbt oder die TypeScript-Fassung wechselt, hält die Regel mit einer Zeile fest.

SCSS und ng generate

--style=scss stellt Komponenten (app.scss) und die globale src/styles.scss auf SCSS um; das gilt im ganzen Kurs. Erzeugt wird mit ng generate:

PowerShell
npx ng generate component kontakte/kontakt-liste
npx ng generate service kontakte/kontakt-daten
CREATE src/app/kontakte/kontakt-liste/kontakt-liste.spec.ts (597 bytes)
CREATE src/app/kontakte/kontakt-liste/kontakt-liste.ts (222 bytes)
CREATE src/app/kontakte/kontakt-liste/kontakt-liste.scss (0 bytes)
CREATE src/app/kontakte/kontakt-liste/kontakt-liste.html (29 bytes)

CREATE src/app/kontakte/kontakt-daten.spec.ts (366 bytes)
CREATE src/app/kontakte/kontakt-daten.ts (88 bytes)

Die Komponente bekommt den Selektor kl-kontakt-liste und die Klasse KontaktListe, der Dienst KontaktDaten den Decorator @Service(). Die Seite „Creating and using services“ nennt ihn eine Kurzform für @Injectable({ providedIn: 'root' }) und trägt dazu keinen Vermerk „neu“ oder „Vorschau“; wir nehmen, was die CLI erzeugt. Die Ordner kontakte, termine, buchung, shared und core unter src/app sind feste Namen der Kladde.

Zoneless in einem Absatz

Die Seite „Zoneless“ sagt: „Zoneless is the default in Angular v21+“, ohne die Bibliothek zone.js. Darum hat die Vorlage kein zone.js in package.json und kein polyfills in angular.json. Angular prüft Ansichten auf Meldungen hin, nach der Seite etwa wenn ein im Template gelesenes Signal sich ändert, ein Ereignis-Listener im Template feuert oder markForCheck gerufen wird. Wer Signals benutzt (0102), muss nichts weiter tun.

Dev-Server und Proxy zur API

ng serve liefert auf http://localhost:4200 aus, bei jeder Änderung neu gebaut. Die Kladde-API läuft auf https://localhost:7180 (Stand K2 prüfen). Ruft der Browser von Port 4200 aus Port 7180 auf, verlangt er CORS-Freigaben (0302). In der Entwicklung umgehen Sie das mit einem Proxy: Der Dev-Server nimmt alles unter /api entgegen und leitet es weiter; der Browser sieht nur Port 4200. Die Datei proxy.conf.json im Projektordner:

JSON
{
  "/api/**": {
    "target": "https://localhost:7180",
    "secure": false
  }
}

Eingehängt wird sie im Ziel serve von angular.json (neben configurations):

JSON
"options": {
  "proxyConfig": "proxy.conf.json"
},

Nach der Seite „Serve“ passt /api/** auf /api, /api/users und /api/users/123, aber nicht auf /api-docs; Änderungen an der Datei brauchen einen Neustart von ng serve. Zur Wirkung von secure sagt die Seite nichts. Beobachtet: Der Testserver auf 7180 benutzte ein selbst ausgestelltes TLS-Schlüsselpaar. Mit "secure": false antwortete curl.exe http://localhost:4200/api/contacts mit 200 und dem JSON des Testservers (via zeigte /api/contacts?page=1&size=20); ohne die Zeile antwortete der Dev-Server mit 502 Bad Gateway. Wie sich das Schlüsselpaar von dotnet dev-certs https verhält, wurde nicht geprüft (offen): Meldet der Proxy 502, ist secure: false der erste Verdacht.

Übung 1

Projekt anlegen, starten, ändern, strict belegen.

  1. Prüfen Sie node --version (Linie 24) und legen Sie im Ordner web das Projekt mit dem Befehl aus dem Text an.
  2. Ändern Sie in src/index.html lang auf de und den <title> auf Kladde.
  3. Ersetzen Sie src/app/app.html durch <main><h1>Kladde</h1></main> und streichen Sie RouterOutlet aus imports in app.ts (sonst meldet der Build ihn womöglich als ungenutzt; nicht geprüft).
  4. Legen Sie proxy.conf.json an und tragen Sie proxyConfig in angular.json ein.
  5. Starten Sie die Kladde-API (Stand K2 prüfen) und npx ng serve. Öffnen Sie http://localhost:4200/ und http://localhost:4200/api/contacts?page=1&size=20. Ändern Sie die Überschrift und sehen Sie die Seite neu laden.
  6. Passen Sie app.spec.ts an (toContain('Kladde') statt Hello, kladde-angular), dann npx ng build und npx ng test --no-watch, jeweils mit gelesenem Exit-Code.
  7. Die Probe: Fügen Sie app.ts protected laenge(text: string | undefined): number { return text.length; } hinzu und bauen Sie. Setzen Sie dann "strict": false in die tsconfig.json, bauen Sie noch einmal und nehmen Sie beides wieder heraus.

So prüfen Sie: Die Seite zeigt „Kladde“; der zweite Aufruf zeigt das JSON der API (contacts, total, page, pageCount). Bau und Test enden mit 0. Die Probe: erster Bau Exit-Code 1 mit TS18048, zweiter Exit-Code 0.

Lösung 1

  • Fehler zu proxy.conf.json oder /api/... landet in 404: Pfad in angular.json und JSON-Syntax prüfen, ng serve neu starten.
  • Der Browser zeigt 502: Die API läuft nicht, hört auf einem anderen Port, oder der Proxy mag ihr Schlüsselpaar nicht (secure: false fehlt).
  • Der Test scheitert mit Hello, kladde-angular: Er prüft noch den Text der Platzhalterseite (Schritt 6).
  • Die Probe baut beim ersten Mal grün: Suchen Sie in allen drei tsconfig-Dateien nach strict; ein Eintrag in der App-Datei überschreibt den der Hauptdatei. Das Projekt ist dann nicht strict.

Was Sie jetzt können

  • Sie sagen, was Angular einer API-Entwicklerin bietet, und lesen Fassung, Node-Bereich und Unterstützungsfenster auf der Seite nach, statt sie zu raten.
  • Sie prüfen Node 24, legen web/kladde-angular an, bauen, starten und testen es und lesen jeweils den Exit-Code.
  • Sie benennen main.ts, app.config.ts, app.ts, angular.json und tsconfig.json und erzeugen Dateien mit ng generate.
  • Sie hängen den Dev-Server mit proxy.conf.json an https://localhost:7180; secure: false gehört nur in die Entwicklung, in der Auslieferung gibt es keinen Proxy (0403).
  • Sie wissen, dass die Vorlage auch ohne Eintrag strict ist, und belegen es mit einem absichtlichen Fehler.

Weiterlesen

Die Kladde: Das Gerüst web/kladde-angular steht mit Präfix kl, SCSS, Vitest und Proxy zur API. Als Nächstes bauen Sie die Kontaktliste aus festen Daten (0102).