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
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
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) {}
}
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.
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.