Kurs Angular · Moduł 5: Serwisy i DI

Komunikacja Między Komponentami przez Serwisy

2 min czytania ·
W tej lekcji2

Serwisy są doskonałym sposobem na komunikację między komponentami - jak gońcy między zamkami.

Przykład: 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 {
  // Stan jako 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([]);
  }
}

Użycie w Komponentach

// header.component.ts - wyświetla ilość
@Component({
  template: `<span>{{ cartService.totalItems() }}</span>`
})
export class HeaderComponent {
  cartService = inject(CartService);
}

// product.component.ts - dodaje do koszyka
@Component({
  template: `<button (click)="addToCart()">Dodaj</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
    });
  }
}

Hasła z dokumentacji w tej lekcji

Widzisz błąd w tej lekcji?

Sprawdź się

Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.

  1. 1. W jaki sposób, według lekcji, komponenty mogą komunikować się i współdzielić stan?

  2. 2. Której funkcji użyjesz w serwisie, aby utworzyć wartość pochodną liczoną automatycznie z innych signali?

To 2 z 4 pytań do tej lekcji. Pozostałe rozwiążesz w grze.

Zadania praktyczne w grze

  • Klikanie w kolejności

    Zbuduj wyrażenie udostępniające sygnał tylko do odczytu (klikaj po kolei):

  • Edytor kodu

    Uzupełnij serwis komunikacyjny używający Signals do współdzielenia stanu.

  • Klikanie w kolejności

    Zbuduj wywołanie czyszczące stan koszyka przez ustawienie pustej tablicy (klikaj po kolei):

  • Układanie w pionie

    Uporządkuj kolejność operacji na serwisie koszyka opartym o signals:

  • Układanie w poziomie

    Ułóż odczyt sygnału totalItems z serwisu w szablonie (jedna linia, bez nawiasów {{ }}):

  • Układanie w pionie

    Uporządkuj budowę komponentu korzystającego ze wspólnego serwisu CartService:

Przydatne artykuły