Mastering Angular Dependency Injection

Mastering Angular Dependency Injection

Mastering Angular Dependency Injection

Angular's Dependency Injection (DI) system is one of its most powerful features. It manages the creation and sharing of services throughout your application, making code modular, testable, and maintainable.

Step 1 — The inject() Function (Modern Approach)

import { Component, inject } from '@angular/core';
import { UserService } from './user.service';
import { Router }      from '@angular/router';

@Component({ selector: 'app-profile', standalone: true, template: `...` })
export class ProfileComponent {
  // inject() replaces constructor injection — cleaner, works in functions
  private userService = inject(UserService);
  private router      = inject(Router);
}

Step 2 — Injection Tokens for Non-Class Dependencies

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

// Define a typed token
export const API_URL = new InjectionToken('API_URL');
export const APP_CONFIG = new InjectionToken('APP_CONFIG');

// Provide in app.config.ts
export const appConfig: ApplicationConfig = {
  providers: [
    { provide: API_URL,    useValue: 'https://api.example.com' },
    { provide: APP_CONFIG, useValue: { maxRetries: 3, timeout: 5000 } },
  ],
};

// Consume anywhere
export class DataService {
  private apiUrl = inject(API_URL);
  private config = inject(APP_CONFIG);
}

Step 3 — Provider Types

providers: [
  // useClass — standard service
  { provide: LogService, useClass: ProductionLogService },

  // useExisting — alias one token to another
  { provide: AbstractLogger, useExisting: LogService },

  // useFactory — dynamic instantiation
  {
    provide: HttpClient,
    useFactory: (handler: HttpHandler) => new HttpClient(handler),
    deps: [HttpHandler],
  },

  // useValue — static value
  { provide: LOCALE_ID, useValue: 'en-US' },
]

Step 4 — Hierarchical Injectors

// Root — shared singleton across the whole app
@Injectable({ providedIn: 'root' })
export class GlobalService { }

// Component — new instance per component (and its children)
@Component({
  providers: [LocalService], // fresh instance for this subtree
})
export class ParentComponent { }
All Comments