Angular course · Module 5: Services and DI
Communication Between Components via Services
In this lesson2
Services are an excellent way for components to communicate - like messengers between castles.
Example: Shared State Service
import { Injectable, signal, computed } from '@angular/core';
export interface CartItem {
id: number;
name: string;
quantity: number;
price: number;
}
@Injectable({ providedIn: 'root' })
export class CartService {
// State as signals
private items = signal<CartItem[]>([]);
// Computed values
readonly cartItems = this.items.asReadonly();
readonly totalItems = computed(() =>
this.items().reduce((sum, item) => sum + item.quantity, 0)
);
readonly totalPrice = computed(() =>
this.items().reduce((sum, item) => sum + item.price * item.quantity, 0)
);
addItem(item: Omit<CartItem, 'quantity'>): void {
const existing = this.items().find(i => i.id === item.id);
if (existing) {
this.items.update(items =>
items.map(i => i.id === item.id
? { ...i, quantity: i.quantity + 1 }
: i
)
);
} else {
this.items.update(items => [...items, { ...item, quantity: 1 }]);
}
}
removeItem(id: number): void {
this.items.update(items => items.filter(i => i.id !== id));
}
clearCart(): void {
this.items.set([]);
}
}Usage in Components
// header.component.ts - displays the count
@Component({
template: `<span>{{ cartService.totalItems() }}</span>`
})
export class HeaderComponent {
cartService = inject(CartService);
}
// product.component.ts - adds to cart
@Component({
template: `<button (click)="addToCart()">Add</button>`
})
export class ProductComponent {
private cartService = inject(CartService);
addToCart(): void {
this.cartService.addItem({
id: this.product.id,
name: this.product.name,
price: this.product.price
});
}
}Docs entries used in this lesson
Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. According to the lesson, how can components communicate and share state?
2. Which function will you use in a service to create a derived value computed automatically from other signals?
These are 2 of 4 questions for this lesson. Solve the rest in the game.
Hands-on tasks in the game
- Click in order
Build the expression that exposes a read-only signal (click in order):
- Code editor
Complete the communication service that uses Signals to share state.
- Click in order
Build the call that clears the cart state by setting an empty array (click in order):
- Vertical ordering
Order the sequence of operations on a signals-based cart service:
- Horizontal ordering
Arrange the reading of the totalItems signal from the service in the template (one line, without the {{ }} braces):
- Vertical ordering
Order the construction of a component that uses the shared CartService: