Angular Services & Dependency Injection
Zeit für wiederverwendbaren Code! Services sind das Herzstück von Angular-Anwendungen. 💉
📋 In diesem Artikel lernst du:
- Was Services sind und warum du sie brauchst
- Dependency Injection (DI) verstehen
- Services erstellen mit
ng generate service - Services in Komponenten injizieren
- Singleton Pattern und providedIn
- Service-Kommunikation zwischen Komponenten
- Observables und RxJS Basics
Was sind Services?
Services sind Klassen, die Logik auslagern die nicht in Komponenten gehört.
Warum Services?
Problem ohne Services:
// user-profile.component.ts
export class UserProfileComponent {
user: User;
ngOnInit() {
// ❌ HTTP-Call direkt in Komponente
fetch('/api/user/123')
.then(res => res.json())
.then(data => this.user = data);
}
}
// user-list.component.ts
export class UserListComponent {
users: User[];
ngOnInit() {
// ❌ Doppelter Code! Same API Call!
fetch('/api/users')
.then(res => res.json())
.then(data => this.users = data);
}
}
Problem:
- ❌ Code-Duplizierung
- ❌ Schwer zu testen
- ❌ Komponenten zu komplex
- ❌ Keine Wiederverwendbarkeit
Lösung mit Service:
// user.service.ts
@Injectable({
providedIn: 'root'
})
export class UserService {
getUser(id: number): Observable<User> {
return this.http.get<User>(`/api/user/${id}`);
}
getAllUsers(): Observable<User[]> {
return this.http.get<User[]>('/api/users');
}
}
// user-profile.component.ts
export class UserProfileComponent {
user: User;
constructor(private userService: UserService) {} // ✅ Service injiziert!
ngOnInit() {
this.userService.getUser(123).subscribe(user => {
this.user = user;
});
}
}
Vorteile:
- ✅ Code an einem Ort
- ✅ Leicht zu testen (Service mocken)
- ✅ Komponenten bleiben simpel
- ✅ Wiederverwendbar überall
Wann nutzt du Services?
Services für:
- ✅ HTTP-Requests (API-Calls)
- ✅ Business Logic (Berechnungen, Validierungen)
- ✅ State Management (Daten zwischen Komponenten teilen)
- ✅ Utility Functions (Date-Formatting, String-Helpers)
- ✅ Browser APIs (LocalStorage, Cookies)
- ✅ Logging & Analytics
NICHT für:
- ❌ UI-Logik (gehört in Komponente)
- ❌ Template-Rendering (gehört in Template)
Was ist Dependency Injection?
Dependency Injection (DI) ist ein Design Pattern, bei dem Abhängigkeiten von außen "injiziert" werden.
Ohne DI (Bad):
export class UserProfileComponent {
private userService: UserService;
constructor() {
// ❌ Komponente erstellt Service selbst
this.userService = new UserService();
}
}
Problem:
- ❌ Tight coupling (fest verdrahtet)
- ❌ Schwer zu testen (kannst Service nicht mocken)
- ❌ Keine Kontrolle über Service-Instanzen
Mit DI (Good):
export class UserProfileComponent {
// ✅ Angular injiziert Service automatisch
constructor(private userService: UserService) {}
}
Vorteile:
- ✅ Loose coupling (flexibel)
- ✅ Leicht zu testen (Service mocken)
- ✅ Angular verwaltet Instanzen (Singleton Pattern)
Angular's DI-Container macht die Magie! ✨
Deinen ersten Service erstellen
Mit Angular CLI:
ng generate service services/user
Oder kurz:
ng g s services/user
Angular erstellt:
CREATE src/app/services/user.service.ts (133 bytes)
CREATE src/app/services/user.service.spec.ts (347 bytes)
Service Anatomy:
src/app/services/user.service.ts:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root' // ⭐ Wichtig! Macht Service singleton
})
export class UserService {
constructor() { }
// Deine Methoden kommen hier hin
}
Erklärung:
@Injectable()- Decorator: Macht Klasse zu einem ServiceprovidedIn: 'root'- Service ist singleton (eine Instanz für ganze App)constructor()- Hier können andere Services injiziert werden
Service mit Logik
Beispiel: Logger Service
logger.service.ts:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class LoggerService {
log(message: string): void {
console.log(`[LOG] ${new Date().toISOString()}: ${message}`);
}
error(message: string): void {
console.error(`[ERROR] ${new Date().toISOString()}: ${message}`);
}
warn(message: string): void {
console.warn(`[WARN] ${new Date().toISOString()}: ${message}`);
}
}
Service nutzen:
app.component.ts:
import { Component, OnInit } from '@angular/core';
import { LoggerService } from './services/logger.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
// ✅ Service im Constructor injizieren
constructor(private logger: LoggerService) {}
ngOnInit() {
this.logger.log('App wurde gestartet!');
}
onButtonClick() {
this.logger.log('Button wurde geklickt');
}
}
So einfach! Angular injiziert den Service automatisch. 🎉
Service mit Daten
Beispiel: User Service mit Mock-Daten
user.service.ts:
import { Injectable } from '@angular/core';
export interface User {
id: number;
name: string;
email: string;
role: 'admin' | 'user';
}
@Injectable({
providedIn: 'root'
})
export class UserService {
private users: User[] = [
{ id: 1, name: 'Max Mustermann', email: 'max@example.com', role: 'admin' },
{ id: 2, name: 'Anna Schmidt', email: 'anna@example.com', role: 'user' },
{ id: 3, name: 'Tom Weber', email: 'tom@example.com', role: 'user' }
];
// Alle User holen
getAllUsers(): User[] {
return this.users;
}
// Einzelnen User finden
getUserById(id: number): User | undefined {
return this.users.find(user => user.id === id);
}
// User hinzufügen
addUser(user: User): void {
this.users.push(user);
}
// User löschen
deleteUser(id: number): void {
this.users = this.users.filter(user => user.id !== id);
}
// User updaten
updateUser(id: number, updates: Partial<User>): void {
const user = this.getUserById(id);
if (user) {
Object.assign(user, updates);
}
}
}
Service in Komponente nutzen:
user-list.component.ts:
import { Component, OnInit } from '@angular/core';
import { UserService, User } from '../services/user.service';
@Component({
selector: 'app-user-list',
template: `
<div class="user-list">
<h2>User Liste</h2>
<div *ngFor="let user of users" class="user-card">
<h3>{{ user.name }}</h3>
<p>{{ user.email }}</p>
<span [class]="'badge ' + user.role">{{ user.role }}</span>
<button (click)="deleteUser(user.id)">Löschen</button>
</div>
<button (click)="addNewUser()">Neuen User hinzufügen</button>
</div>
`,
styles: [`
.user-card {
border: 1px solid #ddd;
padding: 1rem;
margin-bottom: 1rem;
border-radius: 8px;
}
.badge {
padding: 0.25rem 0.5rem;
border-radius: 4px;
font-size: 0.875rem;
}
.badge.admin { background: #ef4444; color: white; }
.badge.user { background: #3b82f6; color: white; }
`]
})
export class UserListComponent implements OnInit {
users: User[] = [];
constructor(private userService: UserService) {}
ngOnInit() {
// ✅ Daten vom Service holen
this.users = this.userService.getAllUsers();
}
deleteUser(id: number) {
this.userService.deleteUser(id);
// Liste neu laden
this.users = this.userService.getAllUsers();
}
addNewUser() {
const newUser: User = {
id: Date.now(),
name: 'Neuer User',
email: 'neu@example.com',
role: 'user'
};
this.userService.addUser(newUser);
this.users = this.userService.getAllUsers();
}
}
✅ Jede Komponente die den UserService injiziert, arbeitet mit denselben Daten!
Dependency Injection im Detail
Provider Scopes
Es gibt 3 Scopes für Services:
1. Root Scope (Empfohlen)
@Injectable({
providedIn: 'root' // ✅ Singleton für ganze App
})
export class UserService { }
Bedeutet:
- Eine Instanz für ganze App
- Tree-shakable (unused Services werden aus Build entfernt)
- Empfohlen für 99% der Fälle
2. Module Scope
// user.service.ts
@Injectable() // Kein providedIn
export class UserService { }
// user.module.ts
@NgModule({
providers: [UserService] // Service hier registriert
})
export class UserModule { }
Bedeutet:
- Eine Instanz pro Modul
- Service nur in diesem Modul verfügbar
3. Component Scope
@Component({
selector: 'app-user-profile',
templateUrl: './user-profile.component.html',
providers: [UserService] // Service nur für diese Komponente
})
export class UserProfileComponent { }
Bedeutet:
- Neue Instanz für jede Komponente
- Service-Daten werden NICHT geteilt
Tipps & Tricks
Welchen Scope wann?
Root Scope (providedIn: 'root'):
- ✅ Meistens die richtige Wahl!
- ✅ Services die Daten zwischen Komponenten teilen
- ✅ HTTP-Services, API-Services
- ✅ State Management Services
Module Scope:
- Feature-spezifische Services
- Lazy-loaded Module Services
- Selten gebraucht
Component Scope:
- ⚠️ Selten nötig!
- Nur wenn jede Komponente eigene Service-Instanz braucht
- Z.B.: Form Validators mit State
Faustregel: Start with providedIn: 'root'!
Dependency Injection Best Practices
Constructor Injection:
// ✅ GOOD: Services im Constructor
constructor(
private userService: UserService,
private logger: LoggerService
) {}
Property Injection (NICHT empfohlen):
// ❌ BAD: Property Injection
@Inject(UserService) userService!: UserService;
Private vs Public:
// ✅ GOOD: Private (nicht im Template gebraucht)
constructor(private userService: UserService) {}
// ⚠️ OK: Public (wenn im Template genutzt)
constructor(public userService: UserService) {}
Multiple Services:
constructor(
private userService: UserService,
private authService: AuthService,
private logger: LoggerService,
private router: Router
) {}
Services für Kommunikation zwischen Komponenten
Services sind perfekt um Daten zwischen Komponenten zu teilen!
Beispiel: Counter Service
counter.service.ts:
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class CounterService {
// ⭐ BehaviorSubject hält aktuellen Wert
private countSubject = new BehaviorSubject<number>(0);
// ⭐ Observable für Komponenten (read-only)
count$: Observable<number> = this.countSubject.asObservable();
getCurrentValue(): number {
return this.countSubject.value;
}
increment(): void {
this.countSubject.next(this.countSubject.value + 1);
}
decrement(): void {
this.countSubject.next(this.countSubject.value - 1);
}
reset(): void {
this.countSubject.next(0);
}
}
Komponente A: Counter Controls
counter-controls.component.ts:
import { Component } from '@angular/core';
import { CounterService } from '../services/counter.service';
@Component({
selector: 'app-counter-controls',
template: `
<div class="controls">
<button (click)="increment()">+</button>
<button (click)="decrement()">-</button>
<button (click)="reset()">Reset</button>
</div>
`
})
export class CounterControlsComponent {
constructor(private counterService: CounterService) {}
increment() {
this.counterService.increment();
}
decrement() {
this.counterService.decrement();
}
reset() {
this.counterService.reset();
}
}
Komponente B: Counter Display
counter-display.component.ts:
import { Component } from '@angular/core';
import { CounterService } from '../services/counter.service';
import { Observable } from 'rxjs';
@Component({
selector: 'app-counter-display',
template: `
<div class="display">
<h2>Aktueller Zähler:</h2>
<p class="counter">{{ count$ | async }}</p>
</div>
`
})
export class CounterDisplayComponent {
count$: Observable<number>;
constructor(private counterService: CounterService) {
// ✅ Observable subscriben (mit async pipe)
this.count$ = this.counterService.count$;
}
}
Parent Component
app.component.html:
<div class="app">
<h1>Counter App mit Services</h1>
<!-- Beide Komponenten teilen sich den Counter-State! -->
<app-counter-display></app-counter-display>
<app-counter-controls></app-counter-controls>
</div>
✅ Wenn du in Controls auf + klickst, updated sich Display automatisch!
Warum? Beide nutzen denselben Service (Singleton)!
RxJS & Observables Basics
Angular nutzt RxJS (Reactive Extensions) für asynchrone Operationen.
Was ist ein Observable?
Ein Observable ist ein Stream von Daten über Zeit.
Analogie:
- Promise: "Ich gebe dir EINEN Wert, irgendwann"
- Observable: "Ich gebe dir VIELE Werte, über Zeit"
BehaviorSubject vs Subject
Subject:
private subject = new Subject<number>();
// Neue Subscriber bekommen NUR neue Werte
BehaviorSubject:
private subject = new BehaviorSubject<number>(0); // Initial Value!
// Neue Subscriber bekommen sofort den aktuellen Wert
// + alle neuen Werte
Nutze BehaviorSubject für State! ✅
Observable Pattern
Standard-Pattern für Services:
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DataService {
// 1. Private Subject (write)
private dataSubject = new BehaviorSubject<Data[]>([]);
// 2. Public Observable (read-only)
data$: Observable<Data[]> = this.dataSubject.asObservable();
// 3. Getter für aktuellen Wert
getData(): Data[] {
return this.dataSubject.value;
}
// 4. Setter für neuen Wert
setData(data: Data[]): void {
this.dataSubject.next(data);
}
// 5. Business Logic
addItem(item: Data): void {
const current = this.dataSubject.value;
this.dataSubject.next([...current, item]);
}
}
Subscribe vs Async Pipe
Subscribe (manuell):
export class MyComponent implements OnInit, OnDestroy {
data: Data[] = [];
private subscription!: Subscription;
ngOnInit() {
// ⚠️ Subscribe
this.subscription = this.dataService.data$.subscribe(data => {
this.data = data;
});
}
ngOnDestroy() {
// ⚠️ WICHTIG: Unsubscribe!
this.subscription.unsubscribe();
}
}
Async Pipe (automatisch):
export class MyComponent {
// ✅ Kein Subscribe nötig!
data$ = this.dataService.data$;
}
<!-- ✅ Async Pipe im Template -->
<div *ngFor="let item of data$ | async">
{{ item.name }}
</div>
Async Pipe macht automatisch unsubscribe! ✅
Häufige Fehler
Fehler 1: Service nicht injiziert
❌ Problem:
export class MyComponent {
users: User[];
ngOnInit() {
// ❌ userService existiert nicht!
this.users = this.userService.getAllUsers();
}
}
✅ Lösung:
constructor(private userService: UserService) {} // Injizieren!
Fehler 2: providedIn vergessen
❌ Problem:
@Injectable() // ❌ Kein providedIn!
export class UserService { }
Error: No provider for UserService!
✅ Lösung:
@Injectable({
providedIn: 'root' // ✅ Root Scope
})
export class UserService { }
Fehler 3: Subscribe Leaks
❌ Problem:
ngOnInit() {
// ❌ Subscribe ohne Unsubscribe = Memory Leak!
this.dataService.data$.subscribe(data => {
this.data = data;
});
}
✅ Lösung 1: Async Pipe
data$ = this.dataService.data$; // ✅ Kein Subscribe
<div *ngFor="let item of data$ | async">
✅ Lösung 2: Unsubscribe
private subscription!: Subscription;
ngOnInit() {
this.subscription = this.dataService.data$.subscribe(...);
}
ngOnDestroy() {
this.subscription.unsubscribe(); // ✅ Cleanup
}
Fehler 4: Service im Component Scope
❌ Problem:
@Component({
selector: 'app-user-list',
providers: [UserService] // ❌ Jede Komponente neue Instanz!
})
export class UserListComponent { }
Resultat: Komponenten teilen sich KEINE Daten!
✅ Lösung:
// Service mit providedIn: 'root'
@Injectable({
providedIn: 'root'
})
export class UserService { }
// Component OHNE providers
@Component({
selector: 'app-user-list',
// providers: [] ← Weg damit!
})
Debugging & Troubleshooting
Service wird nicht injiziert
Problem: "No provider for MyService"
✅ Check:
- Hat Service
@Injectable()Decorator? - Hat Service
providedIn: 'root'? - Ist Service im Constructor injiziert?
// ✅ Complete Service
@Injectable({
providedIn: 'root'
})
export class MyService { }
// ✅ In Komponente
constructor(private myService: MyService) {}
Observable updated nicht
Problem: UI zeigt alte Daten
✅ Check:
- Nutzt du
.next()um Wert zu updaten? - Nutzt du
asyncpipe im Template? - Hast du subscribed?
// ✅ Service
private subject = new BehaviorSubject<Data[]>([]);
data$ = this.subject.asObservable();
updateData(newData: Data[]) {
this.subject.next(newData); // ✅ next() aufrufen!
}
// ✅ Template
<div *ngFor="let item of data$ | async">
Memory Leaks finden
Chrome DevTools:
- Performance Tab → Memory
- Heap Snapshot nehmen
- Komponente mehrmals öffnen/schließen
- Neuen Snapshot nehmen
- Vergleichen → Sollte keine Komponenten im Memory bleiben!
Lösung:
ngOnDestroy() {
this.subscription?.unsubscribe(); // ✅ Cleanup
}
Service-Methoden debuggen
@Injectable({
providedIn: 'root'
})
export class UserService {
getAllUsers(): User[] {
console.log('getAllUsers() called'); // ✅ Debug
const users = this.users;
console.log('Returning users:', users); // ✅ Debug
return users;
}
}
Oder nutze Breakpoints in VS Code/Chrome DevTools!
Praktisches Beispiel: Todo Service
Komplettes Beispiel mit CRUD-Operationen:
todo.service.ts:
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
export interface Todo {
id: number;
title: string;
completed: boolean;
createdAt: Date;
}
@Injectable({
providedIn: 'root'
})
export class TodoService {
private todosSubject = new BehaviorSubject<Todo[]>([
{ id: 1, title: 'Angular lernen', completed: false, createdAt: new Date() },
{ id: 2, title: 'Services verstehen', completed: true, createdAt: new Date() }
]);
todos$: Observable<Todo[]> = this.todosSubject.asObservable();
private nextId = 3;
// Alle Todos holen
getTodos(): Todo[] {
return this.todosSubject.value;
}
// Einzelnes Todo finden
getTodoById(id: number): Todo | undefined {
return this.todosSubject.value.find(todo => todo.id === id);
}
// Todo hinzufügen
addTodo(title: string): void {
const newTodo: Todo = {
id: this.nextId++,
title,
completed: false,
createdAt: new Date()
};
const current = this.todosSubject.value;
this.todosSubject.next([...current, newTodo]);
}
// Todo togglen
toggleTodo(id: number): void {
const current = this.todosSubject.value;
const updated = current.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
);
this.todosSubject.next(updated);
}
// Todo löschen
deleteTodo(id: number): void {
const current = this.todosSubject.value;
const filtered = current.filter(todo => todo.id !== id);
this.todosSubject.next(filtered);
}
// Alle completed löschen
clearCompleted(): void {
const current = this.todosSubject.value;
const filtered = current.filter(todo => !todo.completed);
this.todosSubject.next(filtered);
}
// Stats
getTodoStats(): { total: number; completed: number; active: number } {
const todos = this.todosSubject.value;
return {
total: todos.length,
completed: todos.filter(t => t.completed).length,
active: todos.filter(t => !t.completed).length
};
}
}
todo-list.component.ts:
import { Component } from '@angular/core';
import { TodoService, Todo } from '../services/todo.service';
import { Observable } from 'rxjs';
@Component({
selector: 'app-todo-list',
template: `
<div class="todo-app">
<h1>Todo App mit Services</h1>
<!-- Add Form -->
<div class="add-form">
<input
type="text"
[(ngModel)]="newTodoTitle"
(keyup.enter)="addTodo()"
placeholder="Neues Todo..."
>
<button (click)="addTodo()">Hinzufügen</button>
</div>
<!-- Stats -->
<div class="stats">
<p>Total: {{ stats.total }}</p>
<p>Aktiv: {{ stats.active }}</p>
<p>Erledigt: {{ stats.completed }}</p>
</div>
<!-- Todo List -->
<div class="todo-list">
<div
*ngFor="let todo of todos$ | async"
class="todo-item"
[class.completed]="todo.completed"
>
<input
type="checkbox"
[checked]="todo.completed"
(change)="toggleTodo(todo.id)"
>
<span class="title">{{ todo.title }}</span>
<button (click)="deleteTodo(todo.id)" class="delete">
Löschen
</button>
</div>
</div>
<!-- Actions -->
<div class="actions">
<button (click)="clearCompleted()">
Erledigte löschen
</button>
</div>
</div>
`,
styles: [`
.todo-app {
max-width: 600px;
margin: 2rem auto;
padding: 2rem;
}
.add-form {
display: flex;
gap: 0.5rem;
margin-bottom: 1rem;
}
.add-form input {
flex: 1;
padding: 0.5rem;
border: 1px solid #ddd;
border-radius: 4px;
}
.stats {
display: flex;
gap: 1rem;
margin-bottom: 1rem;
padding: 1rem;
background: #f3f4f6;
border-radius: 8px;
}
.todo-item {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 1rem;
border: 1px solid #ddd;
border-radius: 4px;
margin-bottom: 0.5rem;
}
.todo-item.completed .title {
text-decoration: line-through;
opacity: 0.6;
}
.title {
flex: 1;
}
.delete {
background: #ef4444;
color: white;
border: none;
padding: 0.25rem 0.75rem;
border-radius: 4px;
cursor: pointer;
}
.actions {
margin-top: 1rem;
}
`]
})
export class TodoListComponent {
todos$: Observable<Todo[]>;
newTodoTitle = '';
constructor(private todoService: TodoService) {
this.todos$ = this.todoService.todos$;
}
get stats() {
return this.todoService.getTodoStats();
}
addTodo() {
if (this.newTodoTitle.trim()) {
this.todoService.addTodo(this.newTodoTitle.trim());
this.newTodoTitle = '';
}
}
toggleTodo(id: number) {
this.todoService.toggleTodo(id);
}
deleteTodo(id: number) {
this.todoService.deleteTodo(id);
}
clearCompleted() {
this.todoService.clearCompleted();
}
}
Nicht vergessen FormsModule zu importieren!
app.module.ts:
import { FormsModule } from '@angular/forms';
@NgModule({
imports: [
BrowserModule,
FormsModule // ✅ Für ngModel
],
// ...
})
Zusammenfassung
Du hast gelernt:
- ✅ Services lagern Logik aus Komponenten aus
- ✅ Dependency Injection injiziert Services automatisch
- ✅
@Injectable({ providedIn: 'root' })macht Services singleton - ✅ Services mit
ng generate serviceerstellen - ✅ Services im
constructor()injizieren - ✅ BehaviorSubject für reaktiven State
- ✅ Observable mit
asyncpipe nutzen - ✅ Services zur Kommunikation zwischen Komponenten nutzen
- ✅ Immer unsubscribe oder
asyncpipe nutzen
Key Takeaways:
- Services = Wiederverwendbare Logik
- DI = Loose Coupling + Testability
providedIn: 'root'= Singleton (eine Instanz)- BehaviorSubject + Observable = Reactive State Management
- Async Pipe = Automatisches Subscribe/Unsubscribe
Service Pattern:
@Injectable({ providedIn: 'root' })
export class DataService {
private dataSubject = new BehaviorSubject<Data[]>([]);
data$ = this.dataSubject.asObservable();
getData() { return this.dataSubject.value; }
setData(data: Data[]) { this.dataSubject.next(data); }
}
Nutze Services für alles außer UI! 🎯
Quiz
📝 Quiz
Was macht der @Injectable() Decorator?
📝 Quiz
Was bedeutet providedIn: 'root'?
📝 Quiz
Was ist der Vorteil von Dependency Injection?
Übungen
Übung 1: Calculator Service
Erstelle einen CalculatorService mit Methoden:
add(a, b)subtract(a, b)multiply(a, b)divide(a, b)getHistory()- Array der letzten 10 Berechnungen
Nutze den Service in einer Komponente mit einem Calculator-UI.
Übung 2: Theme Service
Erstelle einen ThemeService der:
- Dark/Light Mode speichert
- Theme ändern kann (
toggleTheme()) - Theme als Observable bereitstellt (
theme$) - Theme in localStorage speichert
Komponente soll Theme ändern können und aktuelles Theme anzeigen.
Übung 3: Shopping Cart Service
Erstelle einen CartService mit:
addItem(product)- Produkt hinzufügenremoveItem(productId)- Produkt entfernenupdateQuantity(productId, quantity)- Menge änderngetTotal()- Gesamtpreis berechnenclearCart()- Warenkorb leerenitems$- Observable mit allen Items
Erstelle 2 Komponenten:
- Product List (Produkte mit "Add to Cart" Button)
- Shopping Cart (Zeigt alle Items im Warenkorb)
Nächste Schritte
Im nächsten Artikel:
- Routing & Navigation
- Router Setup
- Routes definieren
- Navigieren zwischen Seiten
- Route Parameters
- Guards & Resolver
➡️ Weiter zu: Angular Routing & Navigation
Services verstanden! Zeit für Multi-Page Apps! 🚀
Gut gemacht! 🎉
Du hast "Angular Services & Dependency Injection - Logik auslagern" abgeschlossen
Artikel bewerten
Bitte einloggen um zu bewerten
Das könnte dich auch interessieren
Angular Reactive Forms - Formulare professionell erstellen
Meistere Reactive Forms in Angular: Form Validation, Custom Validators, Dynamic Forms und Best Practices für robuste Formulare.
Angular HTTP Client & APIs - Backend-Kommunikation
Lerne HTTP Requests mit Angular HttpClient: GET, POST, PUT, DELETE, Error Handling, Interceptors und RxJS Operators für professionelle API-Integration.
Angular Routing & Navigation - Multi-Page Apps erstellen
Lerne Angular Router kennen, erstelle Routes, navigiere zwischen Seiten, nutze Route Parameters und schütze Routes mit Guards.