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 should contain some configuration data. My problem is that my service has an @Injectable()
decorator and I'm not sure if I can pass it a provide
array in the metadata in which I will inject the configuration as shown in the tutorial. Anybody ever faced such a problem is welcome to share his solution :)
相关问题
- Angular RxJS mergeMap types
- Is there a limit to how many levels you can nest i
- How to toggle on Order in ReactJS
- void before promise syntax
- npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fs
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:
In such application, we have three injectors:
bootstrap
functionAppComponent
injector that can be configured using theproviders
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 theAppComponent
one. To inject elements involved in the injection chain executed forr the component, providers will be looked for first in this injector, then in theAppComponent
one and finally in the application one.This means that when trying to inject the
Service1
into theChildComponent
constructor, Angular2 will look into theChildComponent
injector, then into theAppComponent
one and finally into the application one.Since
Service2
needs to be injected intoService1
, the same resolution processing will be done:ChildComponent
injector,AppComponent
one and application one.This means that both
Service1
andService2
can be specified at each level according to your needs using theproviders
attribute for components and the second parameter of thebootstrap
function for the application injector.This answer could help you:
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, callprovide(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 aproviders
array is not supported.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