Services & Dependency Injection

A component's job is to render a template. Logic that doesn't belong to any one component — talking to an API, sharing state between unrelated components, formatting a date — belongs in a service instead.

Defining a service

TS cart.service.ts
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class CartService {
  private items: string[] = [];

  addItem(name: string) {
    this.items.push(name);
  }

  getItems(): string[] {
    return this.items;
  }
}

@Injectable({ providedIn: 'root' }) registers this class with Angular's dependency injection system and makes a single shared instance available application-wide — no separate registration step needed anywhere else.

Injecting it into a component

TS cart-summary.component.ts
import { Component } from '@angular/core';
import { CartService } from './cart.service';

@Component({
  selector: 'app-cart-summary',
  template: `<p>Items: {{ cart.getItems().length }}</p>`
})
export class CartSummaryComponent {
  constructor(public cart: CartService) {}
}
Behavior
CartSummaryComponent never creates a CartService itself —
it just declares it as a constructor parameter, and Angular
hands it the same shared instance every other component asks for.

This is dependency injection: instead of a component writing new CartService() itself (which would create a separate, disconnected instance), it declares what it needs in its constructor and Angular supplies it — the same shared object, wired up automatically.

Why this matters

Two completely unrelated components — say, a product page that calls addItem() and a header badge that calls getItems() — both end up talking to the exact same CartService instance, without either one knowing the other exists. That's how state gets shared across a real Angular app without passing data through a long chain of component inputs.

Note: providedIn: 'root' makes a service an application-wide singleton — every component gets the same instance. Angular also lets you provide a service at the level of a single component instead (via that component's own providers array), which gives every instance of that component — and its children — a fresh, separate copy. Reach for that only when you specifically want isolated state per component instance, which is far less common than the shared singleton case.