Simplifying Different Types of Providers in Angular

An Angular Service provider delivers a runtime version of a dependency value. Therefore, when you inject a service, the Angular injector looks at the providers to create the instance of the service. It is the provider that determines which instance or value should be injected at the runtime in component, pipes, or directives. There are many jargons involved here, so to understand purpose of types of providers, let us start with creating a service. Let’s say we have a service called ErrorService, which is just logging the error message.


import { Injectable } from '@angular/core';
@Injectable()
export class ErrorService {
logError(message: string) {
console.log(message);
}
}

Now, we can use this service in a component, as shown in the listing below:


import { Component } from '@angular/core';
import { ErrorService } from './errormessage.service';
@Component({
selector: 'app-root',
template: `
<input [(ngModel)]='err' type='text'/>
<button (click)='setError()'>set error</button>
`,
providers: [ErrorService]
})
export class AppComponent {
constructor(private errorservice: ErrorService) {}
err: string;
setError() {
this.errorservice.logError(this.err);
}
}

We are importing the service, passing it in the providers array, and injecting it in the constructor of component. We are calling the service method on click of the button, and you can see error message passed in the console. Very simple right?

Here, Angular will rely on the values passed in the providers array of component (or module) to find which instance should be injected at the run time.

“A Provider determines that how object of certain token can be created.”

So, when you pass a service name in providers array of either component or module, like below:


providers: [ErrorService]

Here, Angular is going to use token value ErrorService and, for token ErrorService, it will create object of ErrorService class. The above syntax is a shortcut of the below syntax:


providers: [{
provide: ErrorService, useClass: ErrorService
}]

The provide property holds the token that serves as the key for

1. locating the dependency value.

2. registering the dependency.

The second property (it is of four types) is used to create the dependency value. There are four possible values of second parameter, as follows:

1. useClass

2. useExisting

3. useValue

4. useFactory

We just saw example of useClass. Now, consider a scenario that you have a new class for better error logging called NewErrorService.


import { Injectable } from '@angular/core';
@Injectable()
export class NewErrorService {
logError(message: string) {
console.log(message);
console.log('logged by DJ');
}
}

useExisting

Now, we want that instead of the instance of ErrorService, the instance of NewErrorService should be injected. Also, ideally, both classes must be implementing the same Interface, which means they will have same method signatures with different implementation. So now, for the token ErrorService, we want the instance of NewErrorService to be injected. It can be done by using useClass, as shown below:


providers: [
NewErrorService,
{provide: ErrorService, useClass: NewErrorService}
]

The problem with the above approach is that there will be two instances of NewErrorService. This can be resolved by the use of useExisting.


providers: [
NewErrorService,
{provide: ErrorService, useExisting: NewErrorService}
]

Now there will be only one instance of NewErrorService and for token ErrorService instance of NewErrorService will be created.

Read full article on the Infragistics blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com