skills/dev-skills/angular-developer/references/di-fundamentals.md
Dependency Injection (DI) is a design pattern used to organize and share code across an application by allowing you to "inject" features into different parts. This improves code maintainability, scalability, and testability.
There are two primary ways code interacts with Angular's DI system:
Angular components, directives, and services automatically participate in DI.
A service is the most common way to share data and functionality across an application. It is a TypeScript class decorated with @Injectable().
Use the providedIn: 'root' option in the @Injectable decorator to make the service a singleton available throughout the entire application. This is the recommended approach for most services.
import {Injectable} from '@angular/core';
@Injectable({
providedIn: 'root', // Makes this a singleton available everywhere
})
export class AnalyticsLogger {
trackEvent(category: string, value: string) {
console.log('Analytics event logged:', {category, value});
}
}
Common uses for services include:
Use Angular's inject() function to request dependencies.
inject() FunctionYou can use the inject() function to get an instance of a service (or any other provided token).
import {Component, inject} from '@angular/core';
import {Router} from '@angular/router';
import {AnalyticsLogger} from './analytics-logger.service';
@Component({
selector: 'app-navbar',
template: `<a href="#" (click)="navigateToDetail($event)">Detail Page</a>`,
})
export class Navbar {
// Injecting dependencies using class field initializers
private router = inject(Router);
private analytics = inject(AnalyticsLogger);
navigateToDetail(event: Event) {
event.preventDefault();
this.analytics.trackEvent('navigation', '/details');
this.router.navigate(['/details']);
}
}
inject() be used? (Injection Context)You can call inject() in an injection context. The most common injection contexts are during the construction of a component, directive, or service.
Valid places to call inject():
import {Component, Directive, Injectable, inject, ElementRef} from '@angular/core';
import {HttpClient} from '@angular/common/http';
// 1. In a Component (Field Initializer & Constructor)
@Component({
/*...*/
})
export class Example {
private service1 = inject(MyService); // ✅ Field initializer
private service2: MyService;
constructor() {
this.service2 = inject(MyService); // ✅ Constructor body
}
}
// 2. In a Directive
@Directive({
/*...*/
})
export class MyDirective {
private element = inject(ElementRef); // ✅ Field initializer
}
// 3. In a Service
@Injectable({providedIn: 'root'})
export class MyService {
private http = inject(HttpClient); // ✅ Field initializer
}
// 4. In a Route Guard (Functional)
export const authGuard = () => {
const auth = inject(AuthService); // ✅ Route Guard
return auth.isAuthenticated();
};