I need to inject a service into another service in an Angular 2
application.
After reading the docs I deduced, that the best approach is to use a Factory Provider. However, two questions have arisen:
1) The docs recommend the creation of a HeroServiceProvider
class with two "code segments":
let heroServiceFactory = (logger: Logger, userService: UserService) => {
return new HeroService(logger, userService.user.isAuthorized);
};
export let heroServiceProvider =
{ provide: HeroService,
useFactory: heroServiceFactory,
deps: [Logger, UserService]
};
My question is how should the class generally look like? Where should one add the above code segments?
2) How should/could one use this factory? I see, it should be imported as:
import { heroServiceProvider } from './hero.service.provider';
@Component({
selector: 'my-selector',
template: `
`,
providers: [heroServiceProvider]
})
How could then the desired parametrized service retrieved and accessed?
1) The first part of your question is easy: you just keep the snippet you provided in a separate file and import it in the component as shown in your question:
import { heroServiceProvider } from './hero.service.provider';
2) As for the actual usage, you don't really need to change service-related code in the component. Just keep using it if the original service was injected. You don't even need to modify your component constructor. The idea of the service provider is that you can customize your service on a per-component basis by having custom service provider for each component, and you would do component-specific initialization in the factory function. Just don't forget to list your service provider in the decorator of your component, Angular is taking care of the rest "automagically".
Today I faced with the same question and found some solution.
1) I found the exact code in angular.io, see following: https://github.com/angular/angular.io/blob/master/public/docs/_examples/dependency-injection/ts/src/app/heroes/hero.service.provider.ts (link updated 15 Mar 2017).
From this code, heroServiceProvider is no need to be a class.
2) In app.module.ts, there is providers property in @NgModule. And you can add the heroServiceProvider in this like following:
By providing service in @NgModule like that, you can use the service in application scope.
I faced same issues to inject on app_initalizer, after long search i found the solution below. May be this is help for your scenario.
I don't have enough points to comment against
@mgmg
's answer, but here is some useful info...I used the provider factory pattern given in docs (and subject of this question) in my own app, but kept getting an error in compilation
Essentially, when a factory dependency is used in a root module, all it's dependencies have to be provided with it.
That means the code block given in
@mgmg
's answer should strictly have the dependent servicesNote, in angular docs here, heroServiceProvider is provided in heroes.component not in app.module, and the references to Logger and UserService are not needed there. I presume these two dependencies are being picked up from higher up the injector tree.
Question 1:
How should the class generally look like? Where should one add the above code segments?
Answer:
You can create a file to contain code for hero service provider and its factory function. This file can be named
hero.service.provider.ts
.And, write code for hero service in another file named
hero.service.ts
.Check out this article about how to use Angular Service Providers to see more examples.
hero.service.provider.ts
file:Question 2: How should/could one use this factory?
Answer:
Following the example code that you provided, a factory could be configured for a service using providers field in
@Component
decorator and the service can be injected through the class constructor or using Angular injector object.However, tree shaking is not working when a factory provider configured this way. Check out this Angular tree shakable service example if you need tree shaking to be working.