Angular Dependency Injection Quick Guide

Thabo Ambrose
3 min readOct 9, 2022

--

A brief summation of the Angular DI design pattern

Angular DI cover image

Dependency injection is the idea of reusing parts of your application in dependent modules. In Angular, one example of the DI system in action would be a component, directive, etc., that depends on some service class or any other class decorated with the @Injectable decorator.

DI system roles

Two key roles exist in the DI system: dependency consumer and provider.

Angular facilitates the interaction between dependency consumers and dependency providers using an abstraction called Injector.

Role 1: Dependency consumer

Some classes (Component, Directive, Service etc.) and even some factory functions.

Class consumerexport class AppComponent {
title = 'my-first-app';
constructor(private myServiceService: MyServiceService){}
}
Factory function consumerexport const HTTP = new InjectionToken('',
{
providedIn: 'root',
factory() {
return inject(HttpClient); // Consumption happens here
},
});

Role 2: Dependency provider

An object configured with a Component or Module describing how the Injector should be configured. The provider tells the injector how to obtain a dependency using an Injection Token. An Injection token can also specify a provider object.

A provider Implements one of the below interfaces.

type Provider = TypeProvider | ValueProvider | ClassProvider | ConstructorProvider | ExistingProvider | FactoryProvider | any[];

Examples of dependency provisioning

1. Provide a dependency from its class decorator (Injectable)

@Injectable({
providedIn: 'root'
})
export class MyServiceService {}

2. Provide a dependency from its consumer.

Example 1 (Let Angular, i.e., the injector, to establish this dependency.)

@Component({
providers: [MyServiceService],
...
})
export class AppComponent {}

Example 2 (Configure how the injector establishes a dependency)

2.1 Using useValue

@Component({
providers: [{
provide: MyServiceService,
useValue: new MyServiceService()

}],
...
})
export class AppComponent {}

2.2 Using useClass

@Component({
providers: [{
provide: MyServiceService,
useClass: MyServiceService

}],
...
})
export class AppComponent {}

2.3 Using useFactory — More flexible than examples 2.1 & 2.2 because you can use the factory pattern to create a dynamic end value of the dependency.

@Component({
providers: [{
provide: MyServiceService,
useFactory: () => new MyServiceService(...someDeps),
deps: [...someDeps]

}],
...
})
export class AppComponent {}

2.4 Using an InjectionToken and useFactory.

const MY_SERVICE_TOKEN = new InjectionToken<MyServiceService>('My basic service');@Component({
providers: [{
provide: MY_SERVICE_TOKEN,
useFactory: () => new MyServiceService()

}],
...
})
export class AppComponent {}

2.5 Using an InjectionToken with a provider

const MY_SERVICE_TOKEN = new InjectionToken<MyService>('Manually constructed MyService', 
{
providedIn: 'root',
factory: () => new MyService(inject(MyDep)),
});
const instance = injector.get(MY_SERVICE_TOKEN);Source: https://angular.io/api/core/InjectionToken#tree-shakable-injectiontoken

Providing a dependency this way makes the Injection token (the dependency) treeshakable

2.6 Usign a Provider in a NgModule: Providing a dependency in the NgModule means that that dependency (A singleton) will be available to all components, directives and pipes declared in that module).

@NgModule({
providers: [MyServiceService],
})
export class AppModule { }
Source: https://angular.io/guide/dependency-injection

The examples from 2 to 2.4 will give you a new instance of the dependency for each of the components’/consumers’ instances.

The Injector

An object in the DI system that can find a named dependency in its cache (Creational design pattern: Object pool or prototype pattern) or create a new one based on the provider configured with the injector.

Injectors are inherited from NgModules or Components by their child components.

You can configure injectors with different providers that can provide different implementations of the same dependency.

Conclusion

Thank you Angular.

Thank you Netanel Basal.

Sources below.

https://angular.io/guide/dependency-injection

https://angular.io/guide/dependency-injection-in-action

--

--