Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to inject a different service based on route in angular 2?

I am somewhat new to Angular 2 and its dependency injection abilities but have not quite been able to find an easy way to change a component dependency based on a route.

I.E. Given a component that takes a service.

MyReusableComponent {
   constructor(private service: ServiceIWantToChange){}
}

Given I am adding a new route in a different part of the web application that will re-use the component.

I want to do something like this: NewAreaRoutingModule

{ 
   path: "newRoute",
   component: MyReusableComponent,
    ** my made up provider area ** -providers: [{provide: 
      ServiceIWantToChange, useClass: MyServiceWithChanges}]
}

This is what my mind ran to as a way to handle the location sensitive dependencies.

I thought I could provide an overriden implementation of the Component the provides a new depenency to the reusable component but I was hoping to just change the dependency in the route.

I've been doing research around resolvers etc but those seem to be more for providing data. I also noticed someone who injected the injector and did a if check to get the right in the component. Seen a couple of different ways. I am sure there is something I am missing about routing and DI but I coulnd't find anything simple. I know there are work arounds but was hoping to find a more elegant solution and just to know if what I want to do is even possible.

Thanks!

Here are the use case details in case I am approaching this wrong in general... In one area of a system I want to use a service that hits one version of rest endpoints on the server and in another part of the system I want to re-use the exact same component but have it send its requests to a different set of end points.

like image 615
Simon Taylor Avatar asked Sep 12 '18 22:09

Simon Taylor


1 Answers

Combining injection tokens with route data gives you the desired result. Provide your services using different injection tokens:

const FIRST_SERVICE_TOKEN = new InjectionToken<string>("FirstService"); 
const SECOND_SERVICE_TOKEN = new InjectionToken<string>("SecondService"); 

@NgModule({
  providers: [
     {
        provide: FIRST_SERVICE_TOKEN,
        useClass: FirstService
     },
     {
        provide: SECOND_SERVICE_TOKEN,
        useClass: SecondService
     }
  ],
})
class AppModule {}

then, specify dependency of each route using route data:

{path: 'first-route', component: MyComponent, data: {requiredService: FIRST_SERVICE_TOKEN}},
{path: 'second-route', component: MyComponent, data: {requiredService: SECOND_SERVICE_TOKEN}}

and finally use the route data to get the corresponding service

export class MyComponent{
   private myService;
   constructor(route: ActivatedRoute, injector:Injector){
       const serviceToken = route.snapshot.data['requiredService'];
       this.myService = injector.get(serviceToken)
   }
}
like image 55
Fartab Avatar answered Oct 12 '22 23:10

Fartab