Dependency Injection
Last updated: Sat Apr 26 2025
When you develop a smaller part of your system, like a module or a class, you may need to use features from other classes. For example, you may need an HTTP service to make backend calls.
When you need to share logic between components, Angular leverages the design pattern of dependency injection that allows you to create a “service” which allows you to inject code into components while managing it from a single source of truth.
A dependency can be provided in multiple places
- At application root level (Preferred)
- at the component level
- at application level using
ApplicationConfig NgModulebased
Example of Calculator Service
- The first step is to add the
@Injectabledecorator to show that the class can be injected. - Providing a service at the application root level using
providedInallows injecting the service into all other classes. - Using
providedInenables Angular and JavaScript code optimizers to effectively remove services that are unused.
import { Injectable } from "@angular/core";
@Injectable({
providedIn: "root",
})
export class Calculator {
add(x: number, y: number) {
return x + y;
}
}
import { Component, inject } from '@angular/core';
import { Calculator } from './calculator';
@Component({
selector: 'app-receipt',
template: `<h1>The total is {{ totalCost }}</h1>`,
})
export class Receipt {
private calculator = inject(Calculator);
totalCost = this.calculator.add(50, 25);
}
In this example, the Calculator is being used by calling the Angular function inject and passing in the service to it.
DI is wired into the Angular framework and allows classes with Angular decorators, such as Components, Directives, Pipes, and Injectables, to configure dependencies that they need.
Two main roles exist in the DI system:
- dependency consumer
- dependency provider.
Angular facilitates the interaction between dependency consumers and dependency providers using an abstraction called Injector.
At application-wide level
@Injectable({
providedIn: "root",
})
class HeroService {}
At Component Level
You can provide services at @Component level by using the providers field of the @Component decorator.
In this case the HeroService becomes available to all instances of this component and other components and directives used in the template.
@Component({
selector: "hero-list",
template: "...",
providers: [HeroService],
})
class HeroListComponent {}
At application level using ApplicationConfig
In the example below, the HeroService is available to all components, directives, and pipes:
export const appConfig: ApplicationConfig = {
providers: [{ provide: HeroService }],
};
Then in main.ts
bootstrapApplication(AppComponent, appConfig);
@NgModule-based applications
use the providers field of the @NgModule decorator to provide a service or other Injectable available at the application level.
