Using Services for Data Sharing
One of the most powerful uses of services is sharing data between components that aren't directly related – like siblings, or components deep in the component tree.
Since services are singletons (when provided at root), they maintain state. Multiple components can inject the same service and access the same data.
Example: Shopping Cart Service
Let's build a shopping cart that multiple components can access.
Step 1: Create the Cart Service
import { Injectable } from '@angular/core';
export interface CartItem {
id: number;
name: string;
price: number;
quantity: number;
}
@Injectable({
providedIn: 'root'
})
export class CartService {
private cartItems: CartItem[] = [];
addToCart(item: CartItem) {
const existingItem = this.cartItems.find(i => i.id === item.id);
if (existingItem) {
existingItem.quantity += item.quantity;
} else {
this.cartItems.push(item);
}
}
getCartItems() {
return this.cartItems;
}
getTotalPrice() {
return this.cartItems.reduce((total, item) => total + (item.price * item.quantity), 0);
}
removeItem(itemId: number) {
this.cartItems = this.cartItems.filter(item => item.id !== itemId);
}
clearCart() {
this.cartItems = [];
}
}
Step 2: Product Component (Adds to Cart)
@Component({
selector: 'app-product',
template: `
<div>
<h3>{{ product.name }}</h3>
<p>Price: {{ product.price | currency }}</p>
<button (click)="addToCart()">Add to Cart</button>
</div>
`
})
export class ProductComponent {
@Input() product: any;
constructor(private cartService: CartService) { }
addToCart() {
this.cartService.addToCart({
id: this.product.id,
name: this.product.name,
price: this.product.price,
quantity: 1
});
alert('Added to cart!');
}
}
Step 3: Cart Component (Displays Cart)
@Component({
selector: 'app-cart',
template: `
<h2>Shopping Cart</h2>
<div *ngIf="cartItems.length === 0">Cart is empty</div>
<ul>
<li *ngFor="let item of cartItems">
{{ item.name }} - {{ item.quantity }} x {{ item.price | currency }}
<button (click)="removeItem(item.id)">Remove</button>
</li>
</ul>
<h3>Total: {{ getTotal() | currency }}</h3>
<button (click)="clearCart()">Clear Cart</button>
`
})
export class CartComponent {
cartItems: CartItem[] = [];
constructor(private cartService: CartService) { }
ngOnInit() {
this.cartItems = this.cartService.getCartItems();
}
getTotal() {
return this.cartService.getTotalPrice();
}
removeItem(id: number) {
this.cartService.removeItem(id);
this.cartItems = this.cartService.getCartItems(); // refresh
}
clearCart() {
this.cartService.clearCart();
this.cartItems = [];
}
}
Now any component can inject CartService and access the same cart data. When one component adds an item, all components see the updated cart.
Two Minute Drill
- Services are perfect for sharing data between components.
- Singleton services (providedIn: 'root') maintain shared state.
- Multiple components can inject and modify the same service data.
- Use methods to update and retrieve data.
- Components must refresh data in ngOnInit to show updates.
Need more clarification?
Drop us an email at career@quipoinfotech.com
