Angular course · Module 5: Services and DI

Communication Between Components via Services

2 min read ·
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. 1. According to the lesson, how can components communicate and share state?

  2. 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:

Useful articles