Skip to main content

Lab 15: Signal Cart Refactor

πŸ“– Resources​

πŸš€ Starter Code​

step-15-album-wholesale-v21-post-signal-computed

In this lab, you'll refactor your shopping cart service from observables to signals. You'll replace BehaviorSubject with signal(), use update() for immutable state changes, and implement computed signals for cart totals.

πŸ“ Instructions​

Step 1: Create Signal-Based Cart​

Replace Observable-based cart with signals:

@Injectable({ providedIn: 'root' })
export class CartService {
// Private writable signal
private cart = signal<Album[]>([]);

// Public computed
cartItems = computed(() => this.cart());

add(album: Album) {
this.cart.update(items => [...items, album]);
}

remove(albumId: number) {
this.cart.update(items => items.filter(item => item.id !== albumId));
}
}

Step 2: Use Computed for Derived State​

Create computed signals for totals:

export class CartComponent {
cartService = inject(CartService);

totalItems = computed(() => this.cartService.cartItems().length);

totalPrice = computed(() =>
this.cartService.cartItems().reduce((sum, item) => sum + item.price, 0)
);
}

Step 3: Update Cart with Immutability​

Use update() for immutable updates:

// Add item
this.cart.update(items => [...items, newItem]);

// Remove item
this.cart.update(items => items.filter(item => item.id !== id));

// Update item
this.cart.update(items =>
items.map(item => item.id === id ? { ...item, quantity: item.quantity + 1 } : item)
);