Angular Providers: useClass, useValue, useFactory & useExisting

In this tutorial, we will learn Angular providers with example. Angular Providers allows us to register classes, functions or values (dependencies) with the Angular dependency injection system. The Providers are registered using the token. The tokens are used to locate the provider. We can create three types of the token. Type Token, string token & Injection Token. The Provider also tells Angular injector how to create the instance of dependency. There are four ways by which you can create the dependency: They are Class Provider (useClass), Value Provider (useValue ), Factory Provider ( useFactory ), and Aliased Class Provider ( useExisting).

Applies to: Angular 2 to the latest edition of i.e. Angular 8. Angular 9, Angular 10

We learned how to build an Angular Services and in the Angular Dependency injection tutorial, we learned to how to Inject the Service into another Angular Component or Service. If you are new to Dependency Injection, we recommend you to go through those tutorials before continuing here.

Suggested Readings

Suggested Readings
Angular Services
Angular Dependency Injection
Angular injector, injectable & inject 
Angular hierarchical dependency Injection

What are Angular Providers

The Angular Provider is an instruction (or recipe) that describes how an object for a certain token is created. The Angular Providers is an array of such instruction (Provider). Each provider is uniquely identified by a token (or DI  Token ) in the Providers Array.

We register the services participating in the dependency injections in the Providers metadata of the @NgModule or @Component or in @Directive. Where you register the dependency defines the scope of the dependency.  

The Angular creates an injector for each component/directive it creates. It also creates a root level injector, which has the app level scope. Each injector gets its own copy of the Providers.

The Angular Components or Angular Services declare the dependencies they need in their constructor. The Injector reads the dependencies and looks for the provider in the providers array using the Token. The injector then instantiates the dependency using the instructions provided in the provider. The Injector then injects the instance of the dependency into the Components/Services.

Configuring the Angular Provider

To Provide an instance of the dependency, we need to register it in the Providers metadata 

In our last tutorial on Angular Dependency injection, we registered our ProductService using the Providers arrays as shown below in the @NgModule

The above is an actual shorthand notation for the following syntax

The above syntax has two properties.


Best Angular Books
The Top 8 Best Angular Books, which helps you to get started with Angular  

Provide

The First property is Provide holds the Token or DI Token. The token is used by the injector to locate the provider in the Providers array. The Token can be either type, a string or an instance of InjectionToken.

Provider

The second property is Provider. It tells the Angular how to create the instance of the dependency. The Angular can create the instance of the Dependency in four different ways. It can create a dependency from the existing service class (useClass). It can inject a value, array or object (useValue). It can use a factory function, which returns the instance of service class or value (useFactory). It can return the instance from an already existing token (useExisting).

DI Token

The injector maintains an internal collection of token-provider map in the Providers array. The token acts as a key to that collection & Injector use the Token (key) to locate the provider.

Types of DI Token

The DI Token can be either type, a string or an instance of InjectionToken.

Type Token

Here the type being injected is used as the token.

For Example, we would like to inject the instance of the ProductService, we will use the ProducService as the token as shown below

The ProductService is then injected to the component by using the following code.

String token

Instead of using a type, we can use a string literal to register the dependency. This is useful in scenarios where the dependency is a value or object etc, which is not represented by a class.

Example

You can then use the Inject the ProductService using the @Inject method

Example:

Injection Token

The Problem with the string tokens is that two developers can use the same string token at a different part of the app. You also do not have any control over the third-party modules, which may use the same token. If the token is reused, the last to register overwrites all previously registered tokens.

String tokens are easier to mistype and that makes it difficult to track & maintain in big applications.

The Angular provides InjectionToken class so as to ensure that the Unique tokens are created. The Injection Token is created by creating a new instance of the InjectionToken class.

InjectionToken Example

First, create a separate file and name it as tokens.ts. Import the InjectionToken from @angular/core library. Create an instance of InjectionToken and assign it to a const API_URL

Open the AppModule and the Token is used to register the value in providers metadata

It is then injected using the @Inject in the constructor of the service/component.

The Types of Provider 

The Angular Dependency Injection provides several types of providers.

  • Class Provider : useClass
  • Value Provider: useValue
  • Factory Provider: useFactory
  • Aliased Class Provider: useExisting

Class Provider: useClass

The Class Provider useClass is used, when you want to provide an instance of the class.

In the above, example ProductService is the Token (or key) and it maps to the ProductService Class. In this case both the Class name and token name match.

The Angular Provides a shortcut in cases where both token & class name matches as follows

You can provide a mock/Fake class for Testing purpose as shown below.

The above example shows us how easy to switch dependencies. 

Value Provider: useValue

The Value Provider useValue is used, when you want to provide a Simple value

This property can be used when you want to provide URL of Service class, Application wide Configuration Option, etc

Use Object.freeze to freeze the value of the configuration, so that it cannot be changed

Factory Provider: useFactory

The Factory Provider useFactory is used when you want to return an object based on a certain condition. The factory function can have an optional argument with dependencies if any.

The above example code uses useValue provider to define USE_FAKE constant

We are then using useFactory to return either FakeProductService or ProductService based on the value of USE_FAKE

Since our Factory Provider depends on  ‘USE_FAKE', we need to specify it on Deps array.

Aliased Provider: useExisting

The Aliased Provider useExisting The provider is used, when you want to use the new provider in place of old Provider.

For Example, in the above example, the ProductService is mapped to the NewProductService token using useExisting Provider. This will return the NewProductService whenever the ProductService is used.

Provider Scope

Where you provide the dependency, defines the lifetime of the dependency.

The service provided in the @ngModule of the root module or any eagerly loaded module are available to be injected everywhere in the application.

The services provided in the @Component, @pipe or @Directive are available to be injected in that component and all the child components

The services provided in the @ngModule of the lazy loaded module are available to be injected in that module and every component, pipe or directive belonging to that Module.

Singleton services

Each Injector creates a singleton object of the dependency registered by the provider.

For Example, consider a service configured in @ngModule. Component A asks for the service it will get a new instance of the service. Now if Component B Asks for the same service, the injector does not create a new instance of the service, but it will reuse the already created service.

But if we register the service in @ngModule and also in Component A. Component A always gets a new instance of the service. While other components gets the instance of the service registered in @ngModule.

Suggested Reading
The angular hierarchical dependency injection system

Summary

We learned how to register dependencies using the Angular Providers. You can download the sample code from the Github repository.  In the next tutorial, we will learn about the Angular injector.

3 thoughts on “Angular Providers: useClass, useValue, useFactory & useExisting”

  1. Good article, easily to understand, but I got one doubt. When we are injecting DI token as a string or as an instance of InjectionToken, why we have to use @Inject() in the contructor?

Leave a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top