Types of Provider

Angular Dependency Injection Provider

The Angular Dependency Injection provides several types of providers.

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

useClass Provider

when you want to provide another class with your provider DI Token then we use useClass class provider. This may be an instance of the same class or another class.

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

The first argument provide is DI Token or a Key.
The second argument useClass: is a DI provider that takes a class. For this case token and provider (class name) are the same.

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

providers :[StudentService]

Example:

We created service : EmployeeService:

import { Injectable } from '@angular/core';
/*
* Here we did not add providedIn: root (Will see later in same post - how * we use 'useClass' with providedIn)
*/
@Injectable()
export class EmployeeService {
  printEmp(): string {
   return 'This is Permanent employee of Company';
  }
}

Case 1: To make it work we will add this service into providers. This is Simple.

providers: [EmployeeService],

Case 2: Now Let’s change the instance of this DI Token with some other class (we have created this class in the same app.module.ts file). This is a Simple Typescript class. Nothing is related to Angular.

// This is Simple Typescript class. Nothing is related to Angular
 export class OffShoreEmpService {
  printEmp(): string {
    return 'This is OffShore employee';
   }
}

providers: [{provide: EmployeeService, useClass: OffShoreEmpService}],

Use of it in a Component.

export class HomeComponent implements OnInit {
  message: string = '';
  constructor(private empService: EmployeeService) { }

  ngOnInit(): void {
      this.message = this.empService.printEmp();
  }
}

Outputs:

For case 1: a message is: ‘This is Permanent employee of Company’
For Case 2: a message is: ‘This is OffShore employee’

So injector is same in HomeComponent constructor function but the result is different for both cases.

useClass with providedIn

// This is simple Class
export class OffShoreEmpService {
  printEmp() {
    console.log('This is OffShore employee');
  }
}

@Injectable({
  providedIn: 'root',
  useClass: OffShoreEmpService // Here we can useClass property to pass another Class
})
export class EmployeeService {
    printEmp() {
    console.log('This is Permanent employee of Company');
  }
}


useFactory Provider

By using useFactory, we can return instances or objects at runtime. This factory pattern is very powerful and gives you a lot of possibilities when it comes to cross-platform development.
Sometimes we add dependencies to the factory to decide whether to return ClassOne or ClassTwo. However, we can add the dependencies with the deps property on the configuration object.

import { Injectable } from '@angular/core';
import { AuthService } from './auth.service';

// Class One : OffShoreEmpService
export class OffShoreEmpService {
  printEmp() {
    console.log('This is OffShore employee');
  }
}
// Class Two: OtherEmployee
export class OtherEmployee {
  printEmp() {
    console.log('This is Other employee')
  }
}

// This is Factory function that return class instance at run time.
// AuthService is dependency here that is optional
export function EmpFactory(auth: AuthService) {
      // Based on isLoggedIn status - returning class object
    return auth.isLoggedIn() ?  new OtherEmployee(): new OffShoreEmpService();
}

@Injectable({
  providedIn: 'root',
  useFactory: EmpFactory,
  deps: [AuthService] // AuthService is dependency here that is optional
})
export class EmployeeService {

  constructor() { }
    printEmp() {
    console.log('This is Permanent employee of Company');
  }
}

Auth service (Used in above example)

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  isLoggedIn() {
    return false;
  }
}


useValue Provider

By using useValue provider, we can return a single value.

@Injectable({
	providedIn: 'root',
	useValue: {
		printEmp: () => 'See, This is JS mount',
	},
})
export class EmployeeService {
	empName = 'This is JS';
	printEmp() {
		return this.empName;
	}
}


useExisting Provider

By using useExistingprovider we can pass an already created service for a request token.

OffShoreEmpService – this service is already flowing into the angular application

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class OffShoreEmpService {
  printEmp(): string {
    return 'This is OffShore employee';
   }
}

Below is EmployeeService and we want to update this with our pre-existing service (created above)
So we will use here useExisting property.

import { Injectable } from '@angular/core';
import { OffShoreEmpService } from './off-shore-emp.service';
  
@Injectable({
	providedIn: 'root',
  useExisting: OffShoreEmpService // Pass you already created service here.
})
export class EmployeeService {
	printEmp() {
		return 'Thi is emp';
	}
}


What is the difference between useClass and useExisting?

  1. If we want to pass a class that is not in the application, then we can create that class and pass it with useClass provider. (Here Class may be simple Typescript Class)
  2. If there is already a service created then we can use useExisting provider. (Here service is Angular service created with @Injectable and providedIn)

If we use useClass for an already created service then what will happen?

In this case, two instances of the same service will be created and that is not acceptable.

Angular 9 https://www.jsmount.com/whats-new-in-angular-9/

Read here the official doc of Angular for Provider…
https://angular.io/guide/dependency-injection-providers

Angular Dependency Injection Provider

Leave a Reply

Your email address will not be published.