Providers
A provider is an instruction to the DI system on how to obtain a value for a dependency. Most of the time, these dependencies are services that you create and provide.
Providing a service
If you already have an app that was created with the Angular CLI, you can create a service using the ng generate CLI command in the root project directory. Replace User with the name of your service.
ng generate service User
This command creates the following UserService skeleton:
User.service.0.ts
import { Injectable } from '@angular/core';
import { UserModule } from './user.module';
@Injectable({
providedIn: UserModule,
})
export class UserService {
}
You can now inject UserService anywhere in your application.
The service itself is a class that the CLI generated and that's decorated with @Injectable(). By default, this decorator has a providedIn property, which creates a provider for the service. In this case, providedIn: 'root' specifies that Angular should provide the service in the root injector.
Provider scope
When you add a service provider to the root application injector, it’s available throughout the app. Additionally, these providers are also available to all the classes in the app as long they have the lookup token.
You should always provide your service in the root injector unless there is a case where you want the service to be available only if the consumer imports a particular @NgModule.
providedIn and NgModules
It's also possible to specify that a service should be provided in a particular @NgModule. For example, if you don't want UserService to be available to applications unless they import a UserModule you've created, you can specify that the service should be provided in the module:
User.service.1.ts
import { Injectable } from '@angular/core';
import { UserModule } from './user.module';
@Injectable({
providedIn: UserModule,
})
export class UserService {
}
The example above shows the preferred way to provide a service in a module. This method is preferred because it enables tree-shaking of the service if nothing injects it. If it's not possible to specify in the service which module should provide it, you can also declare a provider for the service within the module:
User.module.ts
import { NgModule } from '@angular/core';
import { UserService } from './user.service';
@NgModule({
providers: [UserService],
})
export class UserModule {
}
Limiting provider scope by lazy loading modules
In the basic CLI-generated app, modules are eagerly loaded which means that they are all loaded when the app launches. Angular uses an injector system to make things available between modules. In an eagerly loaded app, the root application injector makes all of the providers in all of the modules available throughout the app.
This behavior necessarily changes when you use lazy loading. Lazy loading is when you load modules only when you need them; for example, when routing. They aren’t loaded right away like with eagerly loaded modules. This means that any services listed in their provider arrays aren’t available because the root injector doesn’t know about these modules.
When the Angular router lazy-loads a module, it creates a new injector. This injector is a child of the root application injector. Imagine a tree of injectors; there is a single root injector and then a child injector for each lazy loaded module. The router adds all of the providers from the root injector to the child injector. When the router creates a component within the lazy-loaded context, Angular prefers service instances created from these providers to the service instances of the application root injector.
Any component created within a lazy loaded module’s context, such as by router navigation, gets the local instance of the service, not the instance in the root application injector. Components in external modules continue to receive the instance created for the application root.
Though you can provide services by lazy loading modules, not all services can be lazy loaded.
Limiting provider scope with components
Another way to limit provider scope is by adding the service you want to limit to the component’s providers array. Component providers and NgModule providers are independent of each other. This method is helpful for when you want to eagerly load a module that needs a service all to itself. Providing service in the component limits the service only to that component (other components in the same module can’t access it.)
app.component.ts
@Component({
/* . . . */
providers: [UserService]
})
Providing services in modules vs. components
Generally, provide services the whole app needs in the root module and scope services by providing them in lazy loaded modules.
The router works at the root level so if you put providers in a component, even AppComponent, lazy loaded modules, which rely on the router, can't see them.
Previous: Angular Singleton Service
Next:
Lazy Loading Feature Module
It will be nice if you may share this link in any developer community or anywhere else, from where other developers may find this content. Thanks.
https://w3resource.com/angular/providers.php
- Weekly Trends and Language Statistics
- Weekly Trends and Language Statistics