Setup-Profi Wissensdatenbank

Angular Programmierung: Der Komplett-Guide

1. Die Projekt-Struktur (Statischer Aufbau)

Bevor du die erste Zeile Code schreibst, musst du wissen, wo was hingehört. Angular nutzt eine strikte Ordnerhierarchie, damit Projekte auch bei hunderten Dateien übersichtlich bleiben.

src/app/
├── models/           # Schritt 1: Was wird gespeichert? (Interfaces)
├── services/         # Schritt 2: Woher kommen die Daten? (Logik)
├── components/       # Schritt 3 & 4: Wie sieht es aus? (UI)
│ └── user-list/      # Jede Komponente hat ihren eigenen Ordner
│   ├── user-list.component.ts   # Die Logik
│   └── user-list.component.html # Die Anzeige
└── app.config.ts     # Die Schaltzentrale (Konfiguration)

2. Der Programmier-Workflow (Schritt für Schritt)

In Angular arbeiten wir uns von der Datenstruktur (innen) zur Anzeige (außen) vor.

Schritt 1: Das Model (name.model.ts)

Eine reine TypeScript-Datei für Interfaces. Hier wird kein Code ausgeführt, sondern nur definiert, wie Daten aussehen.

// datei: student.model.ts
export interface Student {
    id: number;
    name: string;
}

Schritt 2: Der Service (name.service.ts)

Die Logik-Zentrale. Hier werden Daten verwaltet, gefiltert oder vom Server geladen.

// datei: student.service.ts
import { Injectable } from '@angular/core';
import { Student } from '../models/student.model';

@Injectable({ providedIn: 'root' })
export class StudentService {
    getStudents(): Student[] { 
        return [{ id: 1, name: 'Tim' }]; 
    }
}

Schritt 3: Die Komponenten-Klasse (name.component.ts)

Die Verbindungsdatei. Sie importiert den Service und bereitet die Daten für das HTML vor.

// datei: student-list.component.ts
import { Component, OnInit } from '@angular/core';
import { StudentService } from '../../services/student.service';
import { Student } from '../../models/student.model';

@Component({
  selector: 'app-student-list',
  templateUrl: './student-list.component.html'
})
export class StudentListComponent implements OnInit {
    liste: Student[] = [];
    constructor(private api: StudentService) {} // Dependency Injection

    ngOnInit() {
        this.liste = this.api.getStudents();
    }
}

Schritt 4: Das Template (name.component.html)

Die Anzeige-Datei. Hier nutzt man Angular-Befehle, um die Daten aus der .ts-Datei sichtbar zu machen.

<!-- datei: student-list.component.html -->
<ul>
    @for (s of liste; track s.id) {
        <li> {{ s.name }} </li>
    }
</ul>

3. Architektur: Warum die strikte Trennung?

Schicht Verantwortung Warum getrennt?
Model Datenstruktur Sicherheit: Verhindert Tippfehler. TypeScript meckert bei Fehlern sofort.
Service Datenlogik Wiederverwendbarkeit: Zehn Komponenten können denselben Service nutzen.
Komponente Zustand & Event-Handling Übersicht: Hier steht nur, *was* passiert, nicht *wie* Daten gespeichert werden.
Template Präsentation (UI) Design-Fokus: Reiner HTML-Code mit Bindings für ungestörtes UI-Design.

Merksatz: Eine Komponente sollte niemals direkt wissen, wie Daten gespeichert werden. Sie fragt einfach den Service. Das macht deine App flexibel!

4. Wichtige Befehle & Syntax

Template-Binding

5. Modernes Control Flow (ab Angular 17)

Die neue Syntax orientiert sich an JavaScript, ist schneller und benötigt keine extra Importe.

@for mit @empty (Die 3D-Druck-Warteschlange)

Das track-Attribut ist jetzt Pflicht für extrem schnelle DOM-Updates.

<h3>Druckaufträge (Bambu Lab P1S)</h3>
<ul>
  @for (print of printQueue; track print.id) {
    <li>
      {{ print.filename }} - Filament: {{ print.material }} ({{ print.progress }}%)
    </li>
  } @empty {
    <li>Keine Druckaufträge in der Warteschlange. Zeit für ein neues Projekt!</li>
  }
</ul>

@if / @else if / @else

@if (hotendTemp > 220) {
  <p class="warning">Achtung: Düse ist sehr heiß!</p>
} @else if (hotendTemp > 50) {
  <p>Düse kühlt ab... Bitte warten.</p>
} @else {
  <p>Düse ist sicher und kann gewechselt werden.</p>
}

6. Fortgeschrittenes Beispiel: HTTP User-Datenabruf

// user.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class UserService {
    constructor(private http: HttpClient) {}
    getUser(id: number) {
        return this.http.get<any>(`https://api.test.de/users/${id}`);
    }
}
// user.component.ts
export class UserComponent implements OnInit {
    user: any;
    constructor(private userService: UserService) {}
    ngOnInit() {
        this.userService.getUser(1).subscribe(res => this.user = res);
    }
}