Anfänger182025-01-31

Angular Components - Die Bausteine deiner App

Verstehe Angular Components im Detail: Erstellen, strukturieren, Component Lifecycle, Input/Output und Parent-Child Kommunikation.

#angular#components#typescript#decorator#lifecycle

Angular Components - Die Bausteine deiner App

Components sind das Herzstück von Angular! In diesem Artikel lernst du alles über Komponenten - von der Erstellung bis zur Kommunikation zwischen Parent und Child.

📋 In diesem Artikel lernst du:

  • Was Components genau sind
  • Wie du Components erstellst (CLI & manuell)
  • Component Anatomy (TypeScript, HTML, CSS)
  • Component Lifecycle Hooks
  • Input & Output für Kommunikation
  • Best Practices für Components

Was ist eine Component?

Eine Component ist ein wiederverwendbarer Baustein deiner Angular-App.

Denke an Components wie Lego-Steine: 🧱

  • Jeder Stein ist in sich abgeschlossen
  • Steine können kombiniert werden
  • Aus vielen Steinen wird ein großes Ganzes

Beispiel: E-Commerce Seite

<app-header>           ← Header Component
  <app-navigation />   ← Navigation Component
</app-header>

<app-product-list>     ← Product List Component
  <app-product-card /> ← Product Card Component (mehrfach!)
  <app-product-card />
  <app-product-card />
</app-product-list>

<app-footer>           ← Footer Component
</app-footer>

Jede Component ist unabhängig und wiederverwendbar!

Component Anatomy - Die 3 Teile

Jede Component besteht aus 3 Dateien:

1. TypeScript-Datei (.ts) - Die Logik

// user-profile.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-user-profile',
  templateUrl: './user-profile.component.html',
  styleUrls: ['./user-profile.component.css']
})
export class UserProfileComponent {
  // Properties (Daten)
  userName = 'Max Mustermann';
  age = 25;
  isAdmin = false;

  // Methods (Funktionen)
  greet() {
    console.log(`Hallo, ich bin ${this.userName}!`);
  }
}

Erklärung:

  • @Component - Decorator der die Klasse zur Component macht
  • selector - HTML-Tag Name (<app-user-profile>)
  • templateUrl - Pfad zum HTML-Template
  • styleUrls - Array von CSS-Dateien
  • userName, age, isAdmin - Properties (Daten der Component)
  • greet() - Method (Funktion der Component)

2. HTML-Datei (.html) - Das Template

<!-- user-profile.component.html -->
<div class="user-profile">
  <h2>{{ userName }}</h2>
  <p>Alter: {{ age }}</p>

  <div *ngIf="isAdmin" class="admin-badge">
    Admin
  </div>

  <button (click)="greet()">
    Begrüßung
  </button>
</div>

Erklärung:

  • {{ userName }} - Interpolation (zeigt Wert)
  • *ngIf - Conditional Rendering
  • (click) - Event Binding

3. CSS-Datei (.css) - Die Styles

/* user-profile.component.css */
.user-profile {
  padding: 20px;
  border: 1px solid #ccc;
  border-radius: 8px;
}

h2 {
  color: #333;
  margin: 0 0 10px 0;
}

.admin-badge {
  background-color: #ff0000;
  color: white;
  padding: 5px 10px;
  display: inline-block;
  border-radius: 4px;
}

button {
  margin-top: 10px;
  padding: 10px 20px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:hover {
  background-color: #0056b3;
}

Wichtig: CSS ist scoped - betrifft nur diese Component!

Component erstellen mit CLI

Der einfachste Weg: Angular CLI

ng generate component user-profile

Oder kürzer:

ng g c user-profile

Was passiert?

CREATE src/app/user-profile/user-profile.component.css (0 bytes)
CREATE src/app/user-profile/user-profile.component.html (28 bytes)
CREATE src/app/user-profile/user-profile.component.spec.ts (657 bytes)
CREATE src/app/user-profile/user-profile.component.ts (299 bytes)
UPDATE src/app/app.module.ts (488 bytes)

Angular CLI erstellt automatisch:

  • ✅ TypeScript-Datei
  • ✅ HTML-Datei
  • ✅ CSS-Datei
  • ✅ Test-Datei (.spec.ts)
  • ✅ Registriert Component im Module!

Component in Unterordner erstellen

ng g c components/user-profile

Erstellt:

src/app/components/user-profile/
  ├── user-profile.component.ts
  ├── user-profile.component.html
  ├── user-profile.component.css
  └── user-profile.component.spec.ts

Ohne Test-Datei erstellen

ng g c user-profile --skip-tests

Inline Template & Styles

ng g c user-profile --inline-template --inline-style

Erstellt nur eine Datei mit Template und Styles inline!

Tipps & Tricks

Component Naming Conventions

Dateinamen:

kebab-case.component.ts
user-profile.component.ts  ✅
UserProfile.component.ts   ❌

Class Namen:

PascalCase
UserProfileComponent  ✅
userProfileComponent  ❌

Selector Namen:

app-prefix + kebab-case
app-user-profile  ✅
userProfile       ❌

CLI Shortcuts

ng g c user-profile              # Voller Befehl
ng g c components/user-profile   # In Unterordner
ng g c user-profile --skip-tests # Ohne Tests
ng g c user-profile -t -s        # Inline alles

Flags:

  • -t = --inline-template
  • -s = --inline-style
  • --skip-tests = Keine .spec.ts Datei

Component Lifecycle Hooks

Angular ruft bestimmte Methoden zu bestimmten Zeitpunkten auf:

Die wichtigsten Lifecycle Hooks:

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

@Component({
  selector: 'app-lifecycle-demo',
  template: '<p>Lifecycle Demo</p>'
})
export class LifecycleDemoComponent implements OnInit, OnDestroy {

  constructor() {
    console.log('1. Constructor - Component wird erstellt');
  }

  ngOnInit() {
    console.log('2. ngOnInit - Component ist initialisiert');
    // API-Calls hier machen!
  }

  ngOnDestroy() {
    console.log('3. ngOnDestroy - Component wird zerstört');
    // Cleanup hier machen!
  }
}

Lifecycle-Reihenfolge:

  1. Constructor - Component wird erstellt
  2. ngOnInit - Component ist initialisiert (einmalig)
  3. ngOnChanges - Input Properties ändern sich
  4. ngDoCheck - Change Detection läuft
  5. ngAfterViewInit - View ist initialisiert
  6. ngOnDestroy - Component wird zerstört

Wann welchen Hook nutzen?

HookWann nutzen?
ngOnInitAPI-Calls, Initialisierung, Setup
ngOnDestroySubscriptions beenden, Timer stoppen
ngOnChangesReagieren auf Input-Änderungen
ngAfterViewInitDOM-Manipulation nach Render

Am häufigsten: ngOnInit und ngOnDestroy!

Input & Output - Component Kommunikation

@Input - Daten von Parent zu Child

Parent Component:

// parent.component.ts
@Component({
  selector: 'app-parent',
  template: `
    <app-child [userName]="parentName" [age]="parentAge">
    </app-child>
  `
})
export class ParentComponent {
  parentName = 'Max';
  parentAge = 25;
}

Child Component:

// child.component.ts
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <div>
      <h3>{{ userName }}</h3>
      <p>Alter: {{ age }}</p>
    </div>
  `
})
export class ChildComponent {
  @Input() userName!: string;  // Empfängt Daten vom Parent
  @Input() age!: number;
}

Fluss: Parent → Child ⬇️

@Output - Events von Child zu Parent

Child Component:

// child.component.ts
import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <button (click)="sendMessage()">
      Nachricht senden
    </button>
  `
})
export class ChildComponent {
  @Output() messageEvent = new EventEmitter<string>();

  sendMessage() {
    this.messageEvent.emit('Hallo vom Child!');
  }
}

Parent Component:

// parent.component.ts
@Component({
  selector: 'app-parent',
  template: `
    <app-child (messageEvent)="handleMessage($event)">
    </app-child>

    <p>Nachricht: {{ receivedMessage }}</p>
  `
})
export class ParentComponent {
  receivedMessage = '';

  handleMessage(message: string) {
    this.receivedMessage = message;
  }
}

Fluss: Child → Parent ⬆️

Vollständiges Beispiel: Todo-Item

Parent (Todo-List):

@Component({
  selector: 'app-todo-list',
  template: `
    <h1>Meine Todos</h1>

    <app-todo-item
      *ngFor="let todo of todos"
      [todoText]="todo.text"
      [isDone]="todo.done"
      (toggleDone)="handleToggle(todo)"
      (deleteTodo)="handleDelete(todo)">
    </app-todo-item>
  `
})
export class TodoListComponent {
  todos = [
    { text: 'Angular lernen', done: false },
    { text: 'Components verstehen', done: true }
  ];

  handleToggle(todo: any) {
    todo.done = !todo.done;
  }

  handleDelete(todo: any) {
    this.todos = this.todos.filter(t => t !== todo);
  }
}

Child (Todo-Item):

@Component({
  selector: 'app-todo-item',
  template: `
    <div class="todo-item" [class.done]="isDone">
      <input
        type="checkbox"
        [checked]="isDone"
        (change)="toggleDone.emit()">

      <span>{{ todoText }}</span>

      <button (click)="deleteTodo.emit()">
        Löschen
      </button>
    </div>
  `,
  styles: [`
    .todo-item { padding: 10px; margin: 5px 0; border: 1px solid #ccc; }
    .todo-item.done { text-decoration: line-through; opacity: 0.6; }
  `]
})
export class TodoItemComponent {
  @Input() todoText!: string;
  @Input() isDone!: boolean;

  @Output() toggleDone = new EventEmitter<void>();
  @Output() deleteTodo = new EventEmitter<void>();
}

Das ist das Angular Component-Pattern! 🎯

Häufige Fehler

Fehler 1: @Input ohne Daten übergeben

FALSCH:

<!-- Parent nutzt Child, aber gibt kein userName -->
<app-child></app-child>
// Child erwartet userName!
@Input() userName!: string;

RICHTIG:

<app-child [userName]="'Max'"></app-child>

Fehler 2: @Output ohne EventEmitter

FALSCH:

@Output() messageEvent: string;  // Falsch!

RICHTIG:

@Output() messageEvent = new EventEmitter<string>();

Fehler 3: Component nicht im Module registriert

Problem:

'app-user-profile' is not a known element

Lösung:

// app.module.ts
@NgModule({
  declarations: [
    AppComponent,
    UserProfileComponent  // ← Component hinzufügen!
  ],
  // ...
})

Tipp: CLI macht das automatisch (ng g c)!

Fehler 4: Selector-Name vergessen

FALSCH:

@Component({
  // selector fehlt!
  templateUrl: './user.component.html'
})

RICHTIG:

@Component({
  selector: 'app-user-profile',
  templateUrl: './user.component.html'
})
🔍

Debugging & Troubleshooting

Component-Probleme debuggen

Problem 1: Component wird nicht angezeigt

Prüfe:

  1. Ist Component im Module registriert? (declarations)
  2. Ist der Selector richtig geschrieben?
  3. Console für Fehler prüfen (F12)

Problem 2: Input-Daten kommen nicht an

// Im Child Component:
ngOnInit() {
  console.log('Empfangene Daten:', this.userName, this.age);
}

Prüfe:

  • Werden Daten im Parent übergeben? [userName]="..."
  • Sind die Property-Namen gleich?
  • Console Logs helfen!

Problem 3: Output funktioniert nicht

// Im Child:
sendMessage() {
  console.log('Event wird emitted');
  this.messageEvent.emit('Test');
}
// Im Parent:
handleMessage(message: string) {
  console.log('Event empfangen:', message);
}

Prüfe:

  • Ist der Event-Handler im Parent definiert?
  • Syntax: (messageEvent)="handleMessage($event)"

Angular DevTools Extension

Chrome/Edge Extension: Angular DevTools

Features:

  • Component-Baum visualisieren
  • Properties live ändern
  • Performance messen

Super hilfreich zum Debuggen!

🎯

Zusammenfassung

Du hast gelernt:

  • ✅ Components sind die Bausteine einer Angular-App
  • ✅ Components bestehen aus .ts, .html, .css (3 Dateien)
  • ✅ CLI erstellt Components: ng g c component-name
  • ✅ Lifecycle Hooks: ngOnInit, ngOnDestroy am wichtigsten
  • ✅ @Input für Daten Parent → Child
  • ✅ @Output mit EventEmitter für Events Child → Parent
  • ✅ CSS in Components ist scoped (nur für diese Component)

Key Takeaways:

  • Nutze Angular CLI zum Erstellen (ng g c)
  • Constructor für Dependency Injection, ngOnInit für Initialisierung
  • @Input = Daten rein, @Output = Events raus
  • Eine Component = ein Feature/UI-Element
  • Keep Components small and focused
  • CSS ist automatisch scoped (kein Konflikt mit anderen Components)

Component Pattern:

Parent Component
  ↓ [Input]
Child Component
  ↑ (Output)
Parent Component

Quiz

📝 Quiz

Welcher CLI-Befehl erstellt eine neue Component?

📝 Quiz

Wofür nutzt man @Input()?

Übungsaufgaben

Aufgabe 1: User-Card Component

Erstelle eine user-card Component:

Anforderungen:

  • Zeigt Name, Email, Avatar (Bild)
  • @Input für alle drei Properties
  • Button "Details anzeigen"
  • @Output Event wenn Button geklickt

Bonus:

  • Hover-Effekt auf der Card
  • Conditional Class wenn User "online" ist

Aufgabe 2: Counter Component

Erstelle eine counter Component:

  • Zeigt einen Zähler an
  • Button "+" erhöht Zähler
  • Button "-" verringert Zähler
  • @Output Event bei jeder Änderung

Aufgabe 3: Product List

Erstelle:

  • product-list Component (Parent)
  • product-card Component (Child)

Array von Produkten im Parent, Child zeigt einzelnes Produkt.

Nächste Schritte

Im nächsten Artikel:

  • Data Binding im Detail
  • Interpolation {{ }}
  • Property Binding []
  • Event Binding ()
  • Two-Way Binding [(ngModel)]

➡️ Weiter zu: Angular Data Binding

Gut gemacht! Components sind die Basis von allem in Angular! 💪

AngularLektion 3 von 10
30% abgeschlossen
Lektion abgeschlossen!

Gut gemacht! 🎉

Du hast "Angular Components - Die Bausteine deiner App" abgeschlossen

Artikel bewerten

0.0 (0 Bewertungen)

Bitte einloggen um zu bewerten