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 machtselector- HTML-Tag Name (<app-user-profile>)templateUrl- Pfad zum HTML-TemplatestyleUrls- Array von CSS-DateienuserName, 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:
- Constructor - Component wird erstellt
- ngOnInit - Component ist initialisiert (einmalig)
- ngOnChanges - Input Properties ändern sich
- ngDoCheck - Change Detection läuft
- ngAfterViewInit - View ist initialisiert
- ngOnDestroy - Component wird zerstört
Wann welchen Hook nutzen?
| Hook | Wann nutzen? |
|---|---|
ngOnInit | API-Calls, Initialisierung, Setup |
ngOnDestroy | Subscriptions beenden, Timer stoppen |
ngOnChanges | Reagieren auf Input-Änderungen |
ngAfterViewInit | DOM-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:
- Ist Component im Module registriert? (declarations)
- Ist der Selector richtig geschrieben?
- 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-listComponent (Parent)product-cardComponent (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! 💪
Gut gemacht! 🎉
Du hast "Angular Components - Die Bausteine deiner App" abgeschlossen
Artikel bewerten
Bitte einloggen um zu bewerten
Das könnte dich auch interessieren
Angular Basics - Was ist Angular?
Lerne Angular von Grund auf kennen: Was ist Angular, warum Angular, Architektur und Konzepte. Der perfekte Einstieg ins Angular Framework.
Angular Data Binding - Daten & UI verbinden
Meistere alle Data Binding Arten in Angular: Interpolation, Property Binding, Event Binding und Two-Way Binding mit ngModel.
Angular Directives - DOM dynamisch steuern
Meistere Angular Directives: *ngIf für Conditional Rendering, *ngFor für Listen, ngClass/ngStyle für Styling und eigene Custom Directives.