How to use DI Token to provide different services instance at runtime for common interface inside angular web app
Published: 2021-03-30 12:48:37

## In this article we will understand use of DI Injection-Token. and We will use This DI token for common tasks and provide services instance at runtime.

#### You can support me

[![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/fv8jyjdsb975y5ztsl2e.png)](https://www.buymeacoffee.com/grdtech)

There are many times comes when we will design angular component, some time component is calling same methods but provide different result for each separate component. For example, Inside our angular application we have two components..

1. ArtsDepartmentEployeeLists
2. ScienceDepartmentEmployeeLists

Above, Both component displays lists of employees, and difference is first component displys arts employee while second component displays Science Employee list. Both Component have common interface api to display only list of employee and nothing else. 

In this situation, First use-case of app is.. we will create one Container component and let container component decides what to render to user. whether it would be arts or science employee list.

Second Use-Case is let admin decides what to render inside whether it would be arts or science employee list and admin decides at runtime of application and switch between lists of employee. This is just a example to decide when to use this method.

To use Injection-Token based service providers inside angular application, 
1. we will first have to figure out common interface of component. 
2. we do not know when at runtime what will user picks.

Now, we have understood, some of the use-case for this mechanism, now we learn how this method is useful in angular.

##InjectionToken(),
      Angular provide us way to extend Dependency Injection mechanism as per our requirement, or we will provide any kind to object or class or factories using InjectionToken inside component, and component injector looks for providers of Token and provide us same instance of InjectionToken. We first Have to create InjectionToken inside our application like this...

### employee-type-interface.ts
```typescript
export type IEmployeeType = "art" | "science";
```
### employee-interface.ts
```typescript
import { IEmployeeType } from "../Tokens/employee-type-interface";

export interface IEmployeeList {
  employeeType: IEmployeeType;
  list();
}
```

In above `IEmployeeList` interface, we declared two members..

1. employeeType : used to pass type of employee like art or science.
2. list() : is method where api call for both component takes place.

Both component needs to have implements this `IEmployeeList` interface.

Now, we create InjectionToken..

### list-token.ts
```typescript
import { InjectionToken } from "@angular/core";
import { IEmployeeList } from "../Tokens/employee-interface";

export const EMPLOYEE_LIST: InjectionToken<IEmployeeList> = new InjectionToken<
  IEmployeeList
>("Token for Employee list");
```

Above, we created `EMPLOYEE_LIST` injection token, this injection token has type of `IEmployeeList` and this token is for Employee list. 

Before we provide injection token to app-module, first we will create two separate service for both art and science employee, and this both service implements our `IEmployeeList` interface and provide implementations.

### art-employee-list.ts

```typescript
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { IEmployeeList } from "../Tokens/employee-interface";
import { IEmployeeType } from "../Tokens/employee-type-interface";

@Injectable()
export class ArtEmployeeService implements IEmployeeList {
  employeeType: IEmployeeType = "art";
  employeeData$ = of([
      { id: 1, employeeType: "art", employeeName: "Avenger" }
  ]);
  constructor(private http: HttpClient) {}
  list() {
    console.log("art-employee list is calling...");
  }
}
```

### science-employee-list.ts

```typescript
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { IEmployeeList } from "../Tokens/employee-interface";
import { IEmployeeType } from "../Tokens/employee-type-interface";

@Injectable()
export class ScienceEmployeeService implements IEmployeeList {
  employeeType: IEmployeeType = "science";
   employeeData$ = of([
     { id: 1, employeeType: "science", employeeName: "Harman" }
   ]);
  constructor(private http: HttpClient) {}
  list() {
    console.log("science-employee list is calling...");
  }
}
```



Now we need to provide this token inside our `app.module.ts`

### app.module.ts
```typescript
@NgModule({
  imports: [BrowserModule, FormsModule, HttpClientModule],
  declarations: [AppComponent, HelloComponent],
  bootstrap: [AppComponent],
  providers: [
    { provide: EMPLOYEE_LIST, useClass: ArtEmployeeService, multi: true },
    { provide: EMPLOYEE_LIST, useClass: ScienceEmployeeService, multi: true }
  ]
})
export class AppModule {}
```

In Above, app.module.ts file we provide our `EMPLOYEE_LIST` token inside providers array, with different implementation using `useClass` modifiers and we will tell angular that this token have multiple implementation using `multi:true`.

Now, all setups are ready to use inside our application, To implement this feature lets create one container-component..

### container.component.ts

```typescript
export class ContainerComponent implements OnInit {
  employeeList$;
  constructor(@Inject(EMPLOYEE_LIST) private employeeList: IEmployeeList[]) {}

  ngOnInit() {}
  onEmployeeList(typeOfEmployee: IEmployeeType) {
    const empList = this.employeeList.find(
      employeeType => employeeType.employeeType === typeOfEmployee
    );
    this.employeeList$ = empList.list();
  }
}
```
First of all, inside constructor of ContainerComponent we inject our `EMPLOYEE_LIST` token, and type of this token is `Array of IEmployeeList`.

This container component has one method `onEmployeeList()` which decides which list of employee data to load inside component at runtime. lets we call this method from template of container component..

### container.component.html

```html
<button (click)="onEmployeeList('art')">Load art-employee data </button>
<hr />
<button (click)="onEmployeeList('science')"> Load science-employee </button>
<hr />
<ng-container *ngIf="employeeList$ | async |json as employeeList">
  {{employeeList}}
</ng-container>
```

Inside template of html onClick of two button, we pass parameter to `onEmployeeList()` method, and then this method decides which injector of service to return back at runtime. 

First this method finds class of employee list using fine() method, and by this instance we will call list() method respectivly. This list() method will return data based on button click whether its art or science... 

At runtime we return instance of service..

There are many benefits of this pattern, 

1. Uniformity in pattern.. when we need another type of employee list to display then we just create own service and provide this service using our custome injection-token with useClass,

2. we will provide data using angular Dependency Injection, so that our application code is well structured and maintable. 

3. use this pattern when you want to provide instance of service at run time.  

#### You can support me

[![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/fv8jyjdsb975y5ztsl2e.png)](https://www.buymeacoffee.com/grdtech)

{% stackblitz angular-ivy-lexwbz %}