April 22nd, 2017
2:54 pm
Declaring Providers for Dependency Injection

Posted under Angular
Tags ,

Providers need to be declared as they ‘provide’ the objects to be injected – in many cases this will be a singleton reused whenever injected (much like a normal Spring bean in Java).

To be visible everywhere in the entire application, they should be declared in the Providers list in the root @NgModule  (e.g. app.module.ts).

However if not used globally, they can be for example registered in a component whereupon they will be visible to that component and its children only.

This angular doc here discusses dependency injection and where to register providers.

This angular doc here is the NgModule faq and also discusses the issue. It points out that registering the providers in the root AppModule (@NgModule as above) is the normal use case, and other cases are rare. In particular it makes the following points:-

Should I add application-wide providers to the root AppModule or the root AppComponent?

Register application-wide providers in the root AppModule, not in the AppComponent.

Lazy-loaded modules and their components can inject AppModule services; they can’t inject AppComponent services.

Register a service in AppComponent providers only if the service must be hidden from components outside the AppComponent tree. This is a rare use case.

More generally, prefer registering providers in modules to registering in components.

Discussion

Angular registers all startup module providers with the application root injector. The services created from root injector providers are available to the entire application. They are application-scoped.

Certain services (such as the Router) only work when registered in the application root injector.

By contrast, Angular registers AppComponent providers with the AppComponent‘s own injector. AppComponent services are available only to that component and its component tree. They are component-scoped.

The AppComponent‘s injector is a child of the root injector, one down in the injector hierarchy. For applications that don’t use the router, that’s almost the entire application. But for routed applications, "almost" isn’t good enough.

AppComponent services don’t exist at the root level where routing operates. Lazy-loaded modules can’t reach them. In the NgModule page sample applications, if you had registered UserService in the AppComponent, the HeroComponent couldn’t inject it. The application would fail the moment a user navigated to "Heroes".

Should I add other providers to a module or a component?

In general, prefer registering feature-specific providers in modules (@NgModule.providers) to registering in components (@Component.providers).

Register a provider with a component when you must limit the scope of a service instance to that component and its component tree. Apply the same reasoning to registering a provider with a directive.

For example, a hero editing component that needs a private copy of a caching hero service should register the HeroService with the HeroEditorComponent. Then each new instance of the HeroEditorComponent gets its own cached service instance. The changes that editor makes to heroes in its service don’t touch the hero instances elsewhere in the application.

Always register application-wide services with the root AppModule, not the root AppComponent.

No Comments »

Comments RSS

Leave a Reply

You must be logged in to post a comment.