Dependency Injection in Angular
Dependency Injection
Dependency injection is a coding pattern in which a class receives its dependencies from external sources rather than creating them itself. It is an important application design pattern. Angular has its own dependency injection framework, which helps make applications flexible, efficient, modular, robust, testable, and maintainable. Dependencies are services or objects that a class needs to perform its function. In Angular 21, the DI framework provides declared dependencies to a class when that class is instantiated, and supports both constructor injection and the modern inject() function.
How DI Works in Angular 21
Angular's DI system works through a hierarchical injector tree. When a component requests a dependency, Angular walks up the injector tree until it finds a provider. The main injector levels are:
inject() Function (Angular 21)
Angular 21 supports the inject() function as an alternative to constructor injection. It can be used in component class fields, making code more concise:
import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { CounterService } from './counter.service';
@Component({
selector: 'app-dashboard',
standalone: true,
template: `
<h2>Dashboard</h2>
<p>Count: {{ counter.count() }}</p>
<button (click)="navigate()">Go Home</button>
`
})
export class DashboardComponent {
// Modern inject() style - no constructor needed
private http = inject(HttpClient);
private router = inject(Router);
counter = inject(CounterService);
navigate() { this.router.navigate(['/home']); }
}
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { CounterService } from './counter.service';
@Component({
selector: 'app-dashboard',
standalone: true,
template: `<h2>Dashboard</h2>`
})
export class DashboardComponent {
// Traditional constructor injection
constructor(
private http: HttpClient,
private router: Router,
public counter: CounterService
) { }
}
Scoped Providers
You can scope a service to a specific component and its children by adding it to the component's providers array. Each instance of the component gets its own service instance.
import { Component, inject } from '@angular/core';
import { CounterService } from './counter.service';
@Component({
selector: 'app-root',
standalone: true,
// Each instance of this component gets its OWN CounterService
providers: [CounterService],
template: `
<p>Count: {{ counter.count() }}</p>
<button (click)="counter.increment()">+</button>
`
})
export class AppComponent {
counter = inject(CounterService);
}
Ready to Level Up Your Skills?
Explore 500+ free tutorials across 20+ languages and frameworks.