8 Angular Komponenten

8.1 Hands-On Einstieg in die Welt der Angular-Komponenten

8.1.1 Die erste Komponente erstellen

Bevor wir in die Theorie eintauchen, lassen Sie uns direkt eine einfache Angular-Komponente erstellen. Öffnen Sie Ihr Terminal und führen Sie folgende Befehle aus:

ng new my-first-app
cd my-first-app
ng generate component greeting

Der erste Befehl ng new my-first-app erstellt ein vollständiges Angular-Projekt mit allen notwendigen Konfigurationsdateien und einer Basisstruktur. Der letzte Befehl ng generate component greeting ist besonders wichtig: Er nutzt den Angular CLI (Command Line Interface), um automatisch eine neue Komponente mit dem Namen greeting zu erstellen. Dabei werden vier Dateien generiert, die zusammen eine funktionsfähige Komponente bilden.

Schauen wir uns an, was Angular für uns generiert hat:

Diese Dateien bilden das Grundgerüst jeder Angular-Komponente: - Die TypeScript-Datei (.ts) enthält die Logik - Die HTML-Datei definiert die Struktur - Die CSS-Datei bestimmt das Aussehen - Die Spec-Datei (.spec.ts) ist für Tests vorgesehen

Öffnen wir die Hauptdatei greeting.component.ts:

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

@Component({
  selector: 'app-greeting',
  templateUrl: './greeting.component.html',
  styleUrls: ['./greeting.component.css']
})
export class GreetingComponent {
  // Hier kommt unsere Komponenten-Logik hin
}

Die @Component-Dekorator-Funktion ist ein spezielles TypeScript-Feature, das der Klasse Metadaten hinzufügt. Diese Metadaten teilen Angular mit, wie die Komponente verwendet werden soll: - selector definiert den HTML-Tag, mit dem wir die Komponente später einbinden (wie ein eigenes HTML-Element) - templateUrl verweist auf die separate HTML-Datei, die die Struktur der Komponente beschreibt - styleUrls gibt an, welche CSS-Dateien für das Styling dieser speziellen Komponente verwendet werden sollen

Bearbeiten wir die Komponente, um sie interaktiver zu gestalten:

  1. Fügen wir der Klasse eine Eigenschaft hinzu:
export class GreetingComponent {
  name: string = 'Welt';
  
  changeName() {
    this.name = 'Angular-Entwickler';
  }
}

Hier fügen wir zwei wichtige Elemente hinzu: - Eine Eigenschaft name vom Typ String mit dem Ausgangswert ‘Welt’ - Eine Methode changeName(), die den Wert dieser Eigenschaft ändert Diese Elemente bilden das Datenmodell und die Verhaltenslogik der Komponente.

  1. Gestalten wir das Template in greeting.component.html:
<div class="greeting-card">
  <h2>Hallo, {{name}}!</h2>
  <button (click)="changeName()">Ändere Namen</button>
</div>

Das Template verwendet zwei grundlegende Konzepte der Angular-Template-Syntax: - Interpolation mit {{name}}: Diese doppelten geschweiften Klammern binden den Wert der name-Eigenschaft aus der Komponenten-Klasse in das Template ein. Wenn sich der Wert ändert, aktualisiert Angular automatisch die Anzeige. - Event-Binding mit (click)="changeName()": Diese Syntax mit runden Klammern verbindet das Klick-Ereignis des Buttons mit der changeName()-Methode unserer Komponente. Bei jedem Klick wird die Methode ausgeführt.

  1. Fügen wir etwas Stil in greeting.component.css hinzu:
.greeting-card {
  border: 2px solid #1976d2;
  border-radius: 8px;
  padding: 20px;
  margin: 20px;
  text-align: center;
  background-color: #f5f5f5;
}

button {
  background-color: #1976d2;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
}

Das Besondere an diesem CSS: Angular kapselt diese Stile automatisch, sodass sie nur für diese spezifische Komponente gelten und nicht den Rest der Anwendung beeinflussen. Dies ist Teil des Shadow DOM-Konzepts, das Angular verwendet, um Komponenten zu isolieren und unerwünschte Stil-Überschneidungen zu vermeiden.

  1. Integrieren wir unsere Komponente in die Hauptanwendung. Öffnen Sie app.component.html und ersetzen Sie den vorhandenen Inhalt durch:
<div class="content">
  <h1>Willkommen zur Angular-Komponenten Demo</h1>
  <app-greeting></app-greeting>
</div>

Hier verwenden wir den im Selektor definierten Tag <app-greeting>. Angular erkennt diesen Tag und ersetzt ihn durch den gerenderten Inhalt unserer Komponente. Dies zeigt die Wiederverwendbarkeit von Komponenten – sie können wie eigene HTML-Elemente in beliebigen Templates eingesetzt werden.

Starten Sie die Anwendung mit ng serve und öffnen Sie http://localhost:4200 in Ihrem Browser. Sie haben gerade Ihre erste interaktive Angular-Komponente erstellt!

8.1.2 Die Anatomie einer Komponente verstehen

Was haben wir gerade getan? Lassen Sie uns die Hauptbestandteile unserer Komponente im Detail analysieren:

  1. @Component Dekorator: Definiert die Metadaten für unsere Komponente
  2. Komponenten-Klasse: Enthält die Logik und Daten
  3. Template: Das HTML mit spezieller Template-Syntax
  4. Styles: CSS-Regeln, die nur für diese Komponente gelten

8.1.3 Der Datenfluss in Angular-Komponenten

Ein entscheidender Aspekt zum Verständnis von Angular-Komponenten ist der Datenfluss:

  1. Initial wird die Komponente mit dem Wert name = 'Welt' erstellt.
  2. Angular rendert das Template und zeigt “Hallo, Welt!” an.
  3. Wenn der Benutzer auf den Button klickt, wird die changeName()-Methode ausgeführt.
  4. Diese ändert den Wert der name-Eigenschaft auf ‘Angular-Entwickler’.
  5. Angular’s Change Detection erkennt diese Änderung automatisch.
  6. Die Anzeige wird aktualisiert, und der Text ändert sich zu “Hallo, Angular-Entwickler!”.

Dies demonstriert das reaktive Verhalten von Angular – Änderungen im Datenmodell führen automatisch zu Aktualisierungen in der Benutzeroberfläche. Sie müssen das DOM nicht manuell manipulieren, wie es bei älteren JavaScript-Frameworks oft nötig war.

8.1.4 Warum Komponenten?

Komponenten sind die grundlegenden Bausteine jeder Angular-Anwendung. Sie können sich eine Komponente wie einen wiederverwendbaren LEGO-Baustein vorstellen. Jede Komponente kapselt drei Dinge:

  1. Ein Stück Benutzeroberfläche (das HTML-Template)
  2. Daten (die Eigenschaften der Klasse)
  3. Verhalten (die Methoden der Klasse)

Diese Kapselung bietet mehrere Vorteile: - Wiederverwendbarkeit: Sie können Komponenten beliebig oft wiederverwenden. - Modularität: Komplexe Anwendungen können in überschaubare Teile zerlegt werden. - Testbarkeit: Komponenten können isoliert getestet werden. - Maintainability: Änderungen an einer Komponente betreffen nur diese, nicht die gesamte Anwendung.

Im Kern ist das Komponenten-basierte Design von Angular eine Umsetzung des Prinzips der Separation of Concerns – jede Komponente kümmert sich nur um einen bestimmten Aspekt der Anwendung.

8.1.5 Das große Ganze

Angular-Anwendungen bestehen typischerweise aus einer Hierarchie von Komponenten. Die AppComponent ist die Wurzelkomponente, in die weitere Komponenten wie unsere GreetingComponent eingebunden werden. Diese Struktur kann beliebig tief sein, wobei Komponenten miteinander kommunizieren können, indem sie Daten und Ereignisse austauschen.

Diese hierarchische Struktur, kombiniert mit Angular’s Change Detection, ermöglicht es, komplexe interaktive Benutzeroberflächen zu erstellen, die effizient und performant sind. ## Datenfluss und Kommunikation

8.1.6 Parent-Child Beziehungen: @Input()

Erweitern wir unser Beispiel um eine Parent-Child Beziehung zwischen Komponenten. Erstellen wir eine neue Komponente:

ng generate component user-greeting

Bearbeiten wir die neue Komponente user-greeting.component.ts:

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-user-greeting',
  templateUrl: './user-greeting.component.html',
  styleUrls: ['./user-greeting.component.css']
})
export class UserGreetingComponent {
  @Input() userName: string = 'Gast';
}

Das Template in user-greeting.component.html:

<div class="user-card">
  <h3>Persönliche Begrüßung für: {{userName}}</h3>
</div>

Styling in user-greeting.component.css:

.user-card {
  background-color: #e1f5fe;
  border: 1px solid #03a9f4;
  border-radius: 4px;
  padding: 10px;
  margin: 10px 0;
}

Jetzt modifizieren wir unsere ursprüngliche GreetingComponent, um die Child-Komponente zu verwenden:

Aktualisieren Sie greeting.component.html:

<div class="greeting-card">
  <h2>Hallo, {{name}}!</h2>
  <button (click)="changeName()">Ändere Namen</button>
  
  <div class="child-component">
    <app-user-greeting [userName]="name"></app-user-greeting>
  </div>
</div>

Fügen Sie einen Stil für den Child-Container in greeting.component.css hinzu:

.child-component {
  margin-top: 20px;
  padding: 10px;
  background-color: #f9f9f9;
  border-radius: 4px;
}

Wir haben gerade: 1. Eine Child-Komponente erstellt 2. Die @Input()-Dekorator verwendet, um Daten von der Parent-Komponente zu empfangen 3. Die Child-Komponente in die Parent-Komponente eingebettet 4. Daten von der Parent- zur Child-Komponente über Property Binding [userName]="name" übergeben

8.1.7 Von unten nach oben: @Output() und EventEmitter

Jetzt wollen wir die Kommunikation in die andere Richtung ermöglichen - von der Child- zur Parent-Komponente:

Bearbeiten wir user-greeting.component.ts:

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-user-greeting',
  templateUrl: './user-greeting.component.html',
  styleUrls: ['./user-greeting.component.css']
})
export class UserGreetingComponent {
  @Input() userName: string = 'Gast';
  @Output() userNameChange = new EventEmitter<string>();
  
  resetName() {
    this.userNameChange.emit('Welt');
  }
}

Aktualisieren wir das Template in user-greeting.component.html:

<div class="user-card">
  <h3>Persönliche Begrüßung für: {{userName}}</h3>
  <button (click)="resetName()">Zurücksetzen</button>
</div>

Aktualisieren wir die Parent-Komponente greeting.component.html, um auf das Event zu hören:

<div class="greeting-card">
  <h2>Hallo, {{name}}!</h2>
  <button (click)="changeName()">Ändere Namen</button>
  
  <div class="child-component">
    <app-user-greeting 
      [userName]="name"
      (userNameChange)="name = $event">
    </app-user-greeting>
  </div>
</div>

Was passiert hier: 1. Die Child-Komponente deklariert einen EventEmitter mit @Output() 2. Bei einem Ereignis (Button-Klick) emittiert die Child-Komponente einen Wert 3. Die Parent-Komponente hört auf dieses Ereignis mit (userNameChange)="name = $event" 4. Wenn das Ereignis eintritt, wird die name-Variable der Parent-Komponente aktualisiert

8.2 Fortgeschrittene Komponenten-Konzepte

8.2.1 Lifecycle Hooks

Angular-Komponenten durchlaufen verschiedene Phasen während ihres Lebenszyklus. Wir können auf diese Phasen mit Lifecycle Hooks reagieren:

import { 
  Component, OnInit, OnChanges, 
  AfterViewInit, OnDestroy, 
  SimpleChanges, Input 
} from '@angular/core';

@Component({
  selector: 'app-lifecycle-demo',
  template: `
    <div class="lifecycle">
      <h3>Lebenszyklus-Demo</h3>
      <p>Status: {{status}}</p>
    </div>
  `,
  styles: [`
    .lifecycle {
      border: 1px solid #673ab7;
      padding: 10px;
      background-color: #ede7f6;
      margin: 10px 0;
    }
  `]
})
export class LifecycleDemoComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy {
  @Input() data: string;
  status: string = 'Initialisierung...';
  
  constructor() {
    console.log('Constructor aufgerufen');
    this.status = 'Komponente konstruiert';
  }
  
  ngOnChanges(changes: SimpleChanges) {
    console.log('OnChanges aufgerufen', changes);
    this.status = 'Eingabe-Eigenschaften geändert';
  }
  
  ngOnInit() {
    console.log('OnInit aufgerufen');
    this.status = 'Komponente initialisiert';
  }
  
  ngAfterViewInit() {
    console.log('AfterViewInit aufgerufen');
    setTimeout(() => {
      this.status = 'View initialisiert';
    });
  }
  
  ngOnDestroy() {
    console.log('OnDestroy aufgerufen');
    // Aufräumarbeiten hier durchführen
  }
}

Die wichtigsten Lifecycle Hooks sind: - ngOnChanges: Wird aufgerufen, wenn sich eine @Input-Eigenschaft ändert - ngOnInit: Wird einmal aufgerufen, nachdem die Komponente initialisiert wurde - ngAfterViewInit: Wird aufgerufen, nachdem die View der Komponente initialisiert wurde - ngOnDestroy: Wird aufgerufen, bevor die Komponente zerstört wird

8.2.2 Content Projection mit ng-content

Content Projection (auch als Transklusion bekannt) ermöglicht es, HTML-Inhalte von außen in eine Komponente einzufügen:

Erstellen wir eine Container-Komponente:

ng generate component content-card

Bearbeiten wir content-card.component.ts:

import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-content-card',
  templateUrl: './content-card.component.html',
  styleUrls: ['./content-card.component.css']
})
export class ContentCardComponent {
  @Input() title: string = 'Karte';
}

Das Template in content-card.component.html:

<div class="content-card">
  <div class="card-header">
    <h3>{{title}}</h3>
  </div>
  <div class="card-body">
    <ng-content></ng-content>
  </div>
</div>

Styling in content-card.component.css:

.content-card {
  border: 1px solid #ccc;
  border-radius: 8px;
  margin: 16px 0;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.card-header {
  background-color: #f5f5f5;
  padding: 10px 16px;
  border-bottom: 1px solid #ccc;
  border-top-left-radius: 8px;
  border-top-right-radius: 8px;
}

.card-body {
  padding: 16px;
}

Verwenden wir die Komponente in app.component.html:

<div class="content">
  <h1>Angular-Komponenten Demo</h1>
  
  <app-greeting></app-greeting>
  
  <app-content-card title="Wichtige Information">
    <p>Dies ist der projizierte Inhalt, der von außen in die Komponente eingefügt wird.</p>
    <button>Aktion ausführen</button>
  </app-content-card>
</div>

Mit <ng-content></ng-content> können wir HTML-Inhalte von außen in unsere Komponente “projizieren”. Dies ist besonders nützlich für wiederverwendbare UI-Elemente wie Karten, Panels oder Dialoge.

8.2.3 Mehrfache Content Projection mit select

Wir können auch mehrere Projektionspunkte mit dem select-Attribut definieren:

Aktualisieren wir content-card.component.html:

<div class="content-card">
  <div class="card-header">
    <h3>{{title}}</h3>
    <div class="header-actions">
      <ng-content select="[card-actions]"></ng-content>
    </div>
  </div>
  <div class="card-body">
    <ng-content></ng-content>
  </div>
  <div class="card-footer">
    <ng-content select="[card-footer]"></ng-content>
  </div>
</div>

Erweitern wir unser CSS in content-card.component.css:

.header-actions {
  display: inline-block;
  float: right;
}

.card-footer {
  padding: 10px 16px;
  background-color: #f5f5f5;
  border-top: 1px solid #ccc;
  border-bottom-left-radius: 8px;
  border-bottom-right-radius: 8px;
}

Verwenden wir die erweiterte Komponente in app.component.html:

<app-content-card title="Erweiterte Karte">
  <p>Dies ist der Hauptinhalt der Karte.</p>
  
  <button card-actions>Bearbeiten</button>
  
  <div card-footer>
    Erstellt am: 19.03.2025
  </div>
</app-content-card>

Mit dem select-Attribut können wir gezielt Inhalte an bestimmte Stellen in unserer Komponente projizieren: - <ng-content> ohne select-Attribut: Standard-Einfügepunkt - <ng-content select="[card-actions]">: Projiziert Elemente mit dem Attribut card-actions - <ng-content select="[card-footer]">: Projiziert Elemente mit dem Attribut card-footer

8.3 Komponenten-Design und Best Practices

8.3.1 Komponenten-Hierarchie und -Struktur

Eine gut durchdachte Komponenten-Hierarchie ist entscheidend für wartbare Angular-Anwendungen:

  1. Smart vs. Presentational Components:
  2. Sinnvolle Granularität:
  3. Wiederverwendbare Komponenten:

8.3.2 Beispiel einer typischen Komponenten-Struktur

8.3.3 Komponenten-Styling und ViewEncapsulation

Angular bietet verschiedene Methoden zur Kapselung von Styles:

@Component({
  selector: 'app-styling-demo',
  template: `
    <div class="demo">
      <h3>Styling-Demo</h3>
      <p>Dieser Text hat einen kapselunsabhängigen Stil.</p>
    </div>
  `,
  styles: [`
    .demo {
      border: 2px solid #ff5722;
      padding: 10px;
      margin: 10px 0;
    }
    
    p {
      color: #ff5722;
    }
  `],
  encapsulation: ViewEncapsulation.Emulated // Standard
})
export class StylingDemoComponent { }

Angular bietet drei Optionen für die Style-Kapselung: - ViewEncapsulation.Emulated: Standard, emuliert Shadow DOM-Kapselung - ViewEncapsulation.None: Keine Kapselung, Styles gelten global - ViewEncapsulation.ShadowDom: Verwendet natives Shadow DOM (nur moderne Browser)

Die emulierte Kapselung fügt automatisch einzigartige Attribute zu Elementen hinzu und transformiert CSS-Selektoren, sodass Styles komponenten-spezifisch bleiben.

8.3.4 Component Change Detection

Angular’s Change Detection sorgt dafür, dass die UI synchron mit dem Zustand der Anwendung bleibt:

import { Component, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'app-performance-demo',
  template: `
    <div class="perf-demo">
      <h3>Performance-optimierte Komponente</h3>
      <p>Aktueller Wert: {{value}}</p>
      <button (click)="increment()">Erhöhen</button>
    </div>
  `,
  styles: [`
    .perf-demo {
      border: 2px dashed #9c27b0;
      padding: 10px;
      margin: 10px 0;
    }
  `],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class PerformanceDemoComponent {
  value = 0;
  
  increment() {
    this.value++;
  }
}

Mit ChangeDetectionStrategy.OnPush prüft Angular nur dann auf Änderungen, wenn: - Eine @Input-Eigenschaft sich ändert (Referenzvergleich) - Ein Event innerhalb der Komponente oder ihrer Kinder ausgelöst wird - Ein Observable, das mit dem Async-Pipe verbunden ist, einen neuen Wert emittiert

Dies kann die Performance erheblich verbessern, insbesondere bei großen Anwendungen mit vielen Komponenten.

8.4 Praxisbeispiel - Eine komplette Feature-Komponente

Zum Abschluss erstellen wir eine komplexe Feature-Komponente, die verschiedene Konzepte kombiniert:

ng generate component todo-manager
ng generate component todo-list
ng generate component todo-item
ng generate component todo-form

todo-manager.component.ts:

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

interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

@Component({
  selector: 'app-todo-manager',
  templateUrl: './todo-manager.component.html',
  styleUrls: ['./todo-manager.component.css']
})
export class TodoManagerComponent {
  todos: Todo[] = [
    { id: 1, title: 'Angular Komponenten verstehen', completed: true },
    { id: 2, title: 'Komponenten-Kommunikation meistern', completed: false },
    { id: 3, title: 'Angular-Anwendung entwickeln', completed: false }
  ];
  
  addTodo(title: string) {
    if (title.trim()) {
      const newId = Math.max(0, ...this.todos.map(t => t.id)) + 1;
      this.todos.push({ id: newId, title, completed: false });
    }
  }
  
  toggleTodo(id: number) {
    this.todos = this.todos.map(todo => 
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    );
  }
  
  deleteTodo(id: number) {
    this.todos = this.todos.filter(todo => todo.id !== id);
  }
}

todo-manager.component.html:

<div class="todo-manager">
  <h2>Aufgaben-Manager</h2>
  
  <app-todo-form (addTodo)="addTodo($event)"></app-todo-form>
  
  <app-todo-list
    [todos]="todos"
    (toggleTodo)="toggleTodo($event)"
    (deleteTodo)="deleteTodo($event)">
  </app-todo-list>
</div>

todo-form.component.ts:

import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-todo-form',
  templateUrl: './todo-form.component.html',
  styleUrls: ['./todo-form.component.css']
})
export class TodoFormComponent {
  @Output() addTodo = new EventEmitter<string>();
  newTodoTitle = '';
  
  onSubmit() {
    this.addTodo.emit(this.newTodoTitle);
    this.newTodoTitle = '';
  }
}

todo-form.component.html:

<div class="todo-form">
  <form (ngSubmit)="onSubmit()">
    <input 
      type="text" 
      placeholder="Neue Aufgabe hinzufügen..." 
      [(ngModel)]="newTodoTitle" 
      name="todoTitle"
      required>
    <button type="submit" [disabled]="!newTodoTitle.trim()">Hinzufügen</button>
  </form>
</div>

todo-list.component.ts:

import { Component, Input, Output, EventEmitter } from '@angular/core';

interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

@Component({
  selector: 'app-todo-list',
  templateUrl: './todo-list.component.html',
  styleUrls: ['./todo-list.component.css']
})
export class TodoListComponent {
  @Input() todos: Todo[] = [];
  @Output() toggleTodo = new EventEmitter<number>();
  @Output() deleteTodo = new EventEmitter<number>();
}

todo-list.component.html:

<div class="todo-list">
  <div *ngIf="todos.length === 0" class="empty-state">
    Keine Aufgaben vorhanden. Fügen Sie eine neue Aufgabe hinzu!
  </div>
  
  <app-todo-item 
    *ngFor="let todo of todos" 
    [todo]="todo"
    (toggle)="toggleTodo.emit($event)"
    (delete)="deleteTodo.emit($event)">
  </app-todo-item>
</div>

todo-item.component.ts:

import { Component, Input, Output, EventEmitter } from '@angular/core';

interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

@Component({
  selector: 'app-todo-item',
  templateUrl: './todo-item.component.html',
  styleUrls: ['./todo-item.component.css']
})
export class TodoItemComponent {
  @Input() todo: Todo;
  @Output() toggle = new EventEmitter<number>();
  @Output() delete = new EventEmitter<number>();
}

todo-item.component.html:

<div class="todo-item" [class.completed]="todo.completed">
  <label>
    <input 
      type="checkbox" 
      [checked]="todo.completed"
      (change)="toggle.emit(todo.id)">
    {{ todo.title }}
  </label>
  <button (click)="delete.emit(todo.id)">Löschen</button>
</div>

todo-item.component.css:

.todo-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  margin: 8px 0;
  border: 1px solid #ddd;
  border-radius: 4px;
  background-color: white;
}

.todo-item.completed label {
  text-decoration: line-through;
  color: #888;
}

.todo-item button {
  background-color: #f44336;
  color: white;
  border: none;
  border-radius: 4px;
  padding: 4px 8px;
  cursor: pointer;
}

Integrieren Sie die Haupt-Komponente in app.component.html:

<div class="content">
  <h1>Angular-Komponenten in der Praxis</h1>
  <app-todo-manager></app-todo-manager>
</div>

Dieses Beispiel zeigt: 1. Eine hierarchische Komponentenstruktur 2. Datenkommunikation über @Input und @Output 3. Event-Handling und Zustandsverwaltung 4. Komponentenspezifisches Styling 5. Bedingte Rendering mit ngIf 6. Listenrendering mit ngFor

Angular-Komponenten sind die Grundbausteine moderner Web-Anwendungen. Durch die Aufteilung der Benutzeroberfläche in kleine, wiederverwendbare Komponenten können wir komplexe Anwendungen auf eine wartbare und verständliche Weise erstellen.

Die wichtigsten Punkte im Überblick:

  1. Komponenten-Struktur: Jede Komponente besteht aus einer TypeScript-Klasse mit @Component-Dekorator, einem HTML-Template und optionalen CSS-Styles.

  2. Komponenten-Kommunikation:

  3. Lebenszyklus-Hooks: ngOnInit, ngOnChanges, ngAfterViewInit und andere ermöglichen Reaktionen auf verschiedene Phasen im Leben einer Komponente.

  4. Content Projection: Mit ng-content können Inhalte von außen in eine Komponente projiziert werden.

  5. Best Practices:

Durch das Meistern dieser Konzepte können Sie skalierbare, wartbare und performante Angular-Anwendungen entwickeln.