I have an Angular2
app with a service
that is used for getting a data from an API. Following this example, I want to create a separate file which s
In fact, Angular2 leverages hierarchical injectors and injectors are linked to components. In short you can define providers only on components (providers
property) or at application level (bootstrap
function).
Regarding services, they will be able to use providers that are visible for the component that initiated the call but you can't define providers at their levels.
Here is a sample:
Application
|
AppComponent
|
ChildComponent
getData() --- Service1 --- Service2
In such application, we have three injectors:
bootstrap
functionAppComponent
injector that can be configured using the providers
attribute of this component. It can "see" elements defined in the application injector. This means if a provider isn't found in this provider, it will be automatically look for into this parent injector. If not found in the latter, a "provider not found" error will be thrown.ChildComponent
injector that will follow the same rules than the AppComponent
one. To inject elements involved in the injection chain executed forr the component, providers will be looked for first in this injector, then in the AppComponent
one and finally in the application one.This means that when trying to inject the Service1
into the ChildComponent
constructor, Angular2 will look into the ChildComponent
injector, then into the AppComponent
one and finally into the application one.
Since Service2
needs to be injected into Service1
, the same resolution processing will be done: ChildComponent
injector, AppComponent
one and application one.
This means that both Service1
and Service2
can be specified at each level according to your needs using the providers
attribute for components and the second parameter of the bootstrap
function for the application injector.
This answer could help you:
This is not supported. For services the providers need to be added to bootstrap(AppComponent, [..., Service, ServiceDependency1, ...])
See also https://github.com/angular/angular/issues/5622
It is a bit strange, but only components can configure dependency injection in Angular (well, and bootstrap()
, but that is essentially the same as the root component). I.e., only components can specify providers.
As @Thierry mentions in his answer, each component in the component tree will get an associated "injector" if the component has a providers
array specified. We can think of this like an injector tree, that is (normally much) sparser than the component tree. When a dependency needs to be resolved, this injector tree is consulted. The first injector that can satisfy the dependency does so. The injector tree is walked up, toward the root component/injector.
So, in order for your service to inject a configuration object dependency, that config object first has to be registered with an injector. I.e., in a component's providers
array, call
provide(stringToken or OpaqueToken, {useValue: MyConfigObject} )
This registration must occur somewhere at or above the component where you want to use/inject your service.
Your service should then be able to @Inject
the registered config object, because it will find it in the injector tree.
Note, since only components can configure providers, the @Injectable()
decorator does not support any configuration options, so a providers
array is not supported.