A standalone cart service that any component can inject — no NgRx needed for this scale.
// stores/cart.store.ts
import { Injectable, signal, computed } from '@angular/core';
export interface CartItem {
id: number;
name: string;
price: number;
quantity: number;
}
@Injectable({ providedIn: 'root' })
export class CartStore {
private _items = signal<CartItem[]>([]);
readonly items = this._items.asReadonly();
readonly itemCount = computed(() => this._items().reduce((s, i) => s + i.quantity, 0));
readonly total = computed(() => this._items().reduce((s, i) => s + i.price * i.quantity, 0));
add(product: { id: number; name: string; price: number }): void {
this._items.update(items => {
const existing = items.find(i => i.id === product.id);
if (existing) {
return items.map(i => i.id === product.id ? { ...i, quantity: i.quantity + 1 } : i);
}
return [...items, { ...product, quantity: 1 }];
});
}
remove(id: number): void {
this._items.update(items => items.filter(i => i.id !== id));
}
updateQuantity(id: number, quantity: number): void {
if (quantity <= 0) { this.remove(id); return; }
this._items.update(items =>
items.map(i => i.id === id ? { ...i, quantity } : i)
);
}
clear(): void { this._items.set([]); }
}
// Usage in any component
readonly cart = inject(CartStore);
// Template
// Total: {{ cart.total() | currency }}
// Items: {{ cart.itemCount() }}
All Comments