In the Angular2 component configuration providers
is one of the keys that we could specify. How are these providers defined and what are they used for?
@Component({
..
providers: [..],
..
})
Note:
Angular2 documentation is gradually maturing but still sparse. It currently defines providers as:
An array of dependency injection providers for services that the
component requires.
This recursive definition isn't very helpful. A more detailed explanation with an example would really help.
Providers are usually singleton (one instance) objects, that other objects have access to through dependency injection (DI).
If you plan to use an object multiple times, for example Http
service in different components, you can ask for same instance of that service (reuse it). You do that with the help of DI by providing a reference to the same object that DI creates for you.
@Component){
..
providers: [Http]
}
..instead of creating new object every time:
@Component){}
class Cmp {
constructor() {
// this is pseudo code, doens't work
this.http = new Http(...options);
}
}
This is an approximation, but that's the general idea behind Dependency Injection - let the framework handle creation and maintenance of reusable objects... Provider is Angular's term for these reusable objects (dependencies).
Register injectables
Providers make injectables known to Angular's DI and define the scope of an injectable (service).
Hierarchy of injectors
Angular's DI creates a tree of injectors (parent > child > grandchild >...) that resembles the structure of your components and directives.
Single instance per provider
Providers are maintained per injector. Each provider provides a single instance of an injectable.
Provider lookup
When a component or directive has a dependency (constructor parameter), DI starts looking on this component's injector for providers. If it has one it requests the instance from this provider and injects it.
If the injector doesn't have a provider for the requested key (type) then the parent injector is visited, up to the root (bootstrap) until a provider is found and its instance can be injected. (If no provider is found DI throws an error).
Define the scope of an injectable instance
This way you can define the scope of a shared service, because DI starts looking from the component where an instance is requested upwards until it finds one.
Singleton or not
How many places you provide an injectable determines how many instances will be created (they are only instantiated if actually requested).
If you want a single instance for your whole application, then provide an injectable only once at the root component (or with bootstrap(AppComponent, [...])
which results in the same behavior.
If you want a new instance for each component A
, then add it to providers of the component A
.
(update) NgModule lazy and non-lazy
With the introduction of NgModule
modules, additional levels were introduced. Providers registered with non-lazy-loaded modules are above the root component in the hierarchy.
Lazy-loaded modules are above the components and directives loaded by these components.
Because providers are read-only after an injector is created, there is no way to add providers from lazy loaded modules to the root injector. Therefore, lazy loaded modules get their own root scope.
See also https://stackoverflow.com/a/45231440/217408
Think of providers like a recipe that tells angular how to inject a service.
We often declare providers in angular this way:
providers: [AnyService]
This is just a short hand for this:
[new Provider(AnyService, {useClass: AnyService})]
Both approaches are saying: Whenever someone requires "AnyService", provide the class "AnyService"
See that even though I'm providing the same class in the example above, in another scenario I could do something like this.
[new Provider(AnyService, {useClass: AnyServiceCustom})]
But in both scenarios, constructor would remain the same:
constructor( private _anyService: AnyService) {
}
To understand it better you need to understand how dependency injection works in Angular 2 as providers are directly related to it.
This is a must-read for every angular 2 developer.
https://angular.io/docs/ts/latest/guide/dependency-injection.html?The%20Provider%20class%20and%20provide%20function#!#injector-providers
import { service_name} from '../path';
@Component({
selector: 'selector_name',
templateUrl: './html file name ',
styleUrls: ['./css file name '],
providers: [ ./'service_name'];
})
export class AppComponent {
constructor(private Service_name: service_name) {
//enter code here
}