Services & Dependency Injection

📚 What are Services?

Services are classes that handle business logic, data access, and shared functionality.

  • Dependency Injection (DI): Angular's powerful pattern for providing dependencies
  • Singleton: providedIn: 'root' creates one instance for entire app
  • inject() function: Modern way to inject dependencies (v14+)
  • Hierarchical Injectors: Component-level providers create separate instances

🎯 Interview Questions

  • Q1: What is Dependency Injection?
  • A: Design pattern where dependencies are provided rather than created. Angular's DI creates and manages instances.
  • Q2: What is the difference between providedIn: 'root' vs component-level providers?
  • A: 'root' creates singleton for entire app. Component-level creates new instance per component (and its children).
  • Q3: What is inject() function vs constructor injection?
  • A: inject() is functional approach (v14+), works outside constructors. Constructor injection is class-based (older approach).
  • Q4: What are Injection Tokens?
  • A: Used for injecting non-class values like config objects or primitives.

🔧 Live Demo - Shared Service

Counter Service (Singleton)

Count: 0

This value is shared across the entire app!

User Service

  • • Alice
  • • Bob
  • • Charlie

📋 Provider Types

Provider TypeDescription
useClassProvide a different class implementation
useValueProvide a static value
useFactoryProvide value from a factory function
useExistingAlias to another provider

💻 Service Code


import { Injectable, inject, signal } from '@angular/core';

// Singleton Service (providedIn: 'root')
@Injectable({
  providedIn: 'root', // Tree-shakable singleton
})
export class CounterService {
  private readonly count = signal(0);
  
  // Expose read-only signal
  readonly currentCount = this.count.asReadonly();

  increment(): void {
    this.count.update(v => v + 1);
  }
}

// Component using the service
@Component({...})
export class MyComponent {
  // Modern inject() function (v14+)
  private readonly counterService = inject(CounterService);
  
  // Or constructor injection (older approach)
  // constructor(private counterService: CounterService) {}
}

// Injection Token for non-class values
import { InjectionToken } from '@angular/core';

export const API_URL = new InjectionToken<string>('API_URL');

// Providing in app config
export const appConfig = {
  providers: [
    { provide: API_URL, useValue: 'https://api.example.com' }
  ]
};