Providers Property
We know that @Component decorator functions take object, and this object contains a lot of properties. So in this article we will learn about Providers properties which is Inherited from Directive decorator .
providers metadata is available in the @NgModule() decorator and @Component() decorator. provider’s metadata is used to configure the provider.
A provider provides concrete and runtime version of a dependency value. The injector injects the objects provided by provider into components and services. Therefore, it is necessary to configure a service with the provider, otherwise the injector will not be able to inject it.
The injector injects the objects provided by provider into components and services. Only those classes configured by providers are available for dependency injection (DI).
Angular offers different types of providers as a class provider, alias provider, value provider and factory provider as shown below.
Injector creates a singleton object of a class configured by providers.
Providers can be configured at Two level as shown below.
- Module level
- Component level
Module level
Providers can be configured at the module level. when providers of @NgModule() decorator configure a service in the application module, that service will be available for injection of dependencies on all those components that are configured in the metadata declarations of that decorator @NgModule().
In short, if a service is configured using the provider in the module, it will be available for all components configured in module for dependency injection.
Component level
Providers can be configured at the component level. when @Component() decorator providers configure a service in a component, that service will be available for injecting dependencies into the current component and its secondary components up to the bottom component.
In short, if a service is configured using the provider in the component, it will be available in the current component and its children component up to the bottom component.
Suppose that in our application, if we have configured a service using the providers in the root component (app.component.ts), it will be available in all the components and services of the application for injecting dependencies.
In general, we set up a service using the providers as shown below.
providers: [ AnyService ]
Injector
Injector creates a singleton object of the class configured by the provider for DI. But if we have configured a service in more than one place using a provider, then object created by the injector will be different.
Suppose we have two components and have the respective child components. Suppose that both components configure the same service class. Now, for the first component, the injector will create a singleton object that will be available for the first components and its child components up to the bottom component. For the second component, the injector will create a different singleton object that will be available for the second component and its child components up to the bottom component for DI.
Providers metadata is divided into two parts:
- Token: the first part is a token configured by the provide attribute.
- Provider definition object: the second part is the provider definition object configured by useClass, useExisting, useValue and useFactory.
@Injectable()
@Injectable() decorator is a marker used at the class level. @Injectable() is the part of @ angular/core API.It tells Injector that this class is available for creation by Injector. We use @Injectable () in our service so that the service object can be created automatically for dependency injection in any component or any other service class.
@Injectable() is also responsible for creating an instance of angular component, pipe, directive, etc. This is possible because @Component, @Pipe and @Directive decorators use the @Injectectable decorator. If our service class decorated with @Injectable() is dependent on other service class, then we should not worry about its creation and injection of the dependency will be performed automatically by Injector.
If our service class does not depend on other types of service, it is not necessary to decorate our service class with the @Injectable () decorator. Also the object of this class can be created by Injector for addiction injection.
But it is better to use @Injectable() decorator in this case also because in the future our service class may need dependency on other service class. At that time, Injector will generate an error for our service class if it is not decorated with @Injectable(). Therefore, it is better to use the @Injectable() decorator always in our service class. A class decorated with @Injectable() is created as follows.
@Injectable() export class AnyService { }
InjectionToken
InjectionToken creates a token that can be used in the DI (dependency injection) provider. If we want to inject simple data like strings, array, dates, numbers, etc. then for dependency injection, we need to create an instance of InjectionToken as follows.
export const HELLO_MESSAGE = new InjectionToken <string>('Hello!');
Now use the previous constant in the providers.
providers: [ { provide: HELLO_MESSAGE, useValue: 'Hello World!' } ]
When we run the dependency injection of HELLO_MESSAGE using a constructor in any component or service, we get its value as Hello World! We can inject string, array, dates, numbers, etc. with the help of the @Inject() decorator using the constructor as follows.
constructor(@Inject(HELLO_MESSAGE) private message: string) { }
We will see different types of providers such as class provider, alias provider, value provider and factory provider in next chapter step by step.