Dependency Injection
Dependency Injection
Section titled βDependency InjectionβWhat it means
Section titled βWhat it meansβDependency Injection (DI) is a pattern where a class declares what it needs (its dependencies) instead of creating them itself, and a framework-managed injector supplies them. Angularβs DI system provides services to components, directives, and other services automatically based on constructor parameters (or the modern inject() function), which makes testing easier (swap in fakes) and avoids tightly-coupled, hard-to-reuse code.
Examples
Section titled βExamplesβ@Injectable({ providedIn: 'root' }) // registered once, shared app-wide (singleton)export class AuthService { isLoggedIn(): boolean { return true; }}
@Component({ selector: 'app-dashboard', template: `...` })export class DashboardComponent { // Constructor injection -- Angular supplies an AuthService instance automatically constructor(private auth: AuthService) {}
ngOnInit() { console.log(this.auth.isLoggedIn()); }}
// Modern functional style (Angular 14+), often used outside constructors tooimport { inject } from '@angular/core';
@Component({ selector: 'app-dashboard', template: `...` })export class DashboardComponent { private auth = inject(AuthService);}Common mistake
Section titled βCommon mistakeβInstantiating a service manually with new instead of letting Angular inject it β this bypasses the DI system entirely, giving you a disconnected instance that doesnβt share state with the rest of the app and canβt be swapped out in tests.
export class DashboardComponent { private auth = new AuthService(); // bypasses DI -- own private instance, not the shared singleton}
// Correct: let Angular provide the shared instanceexport class DashboardComponent { private auth = inject(AuthService); // gets the SAME instance every other component uses}Quick practice
Section titled βQuick practiceβ-
What does
providedIn: 'root'on@Injectable()mean?Answer
The service is registered app-wide as a singleton β Angular creates one shared instance the first time it's needed, and every component/service that injects it gets that same instance. -
Why is manually calling
new AuthService()inside a component considered a mistake?Answer
It bypasses Angular's DI system, creating a disconnected instance rather than the shared singleton β this breaks assumptions about shared state and makes the component harder to test (you can't substitute a mock). -
Whatβs the modern alternative to constructor injection introduced in Angular 14+?
Answer
Theinject()function, which can retrieve a dependency from anywhere in an injection context (constructors, field initializers, and certain other Angular APIs), not just as a constructor parameter.