I just started using the feature module + lazily loaded routing part of angular framework, and have a bit of trouble getting used to the nuances. One thing that comes up now and again is how to store the services and interfaces- should they go in the providers array of only the modules that use them? or should some kind of main service module be injected into the root module?
I have understood from various tutorials that services and interfaces should not go in the core module or shared module.
what i was doing before hand:
//service.module.ts
@NgModule({
imports: [],
exports: [],
declarations: [],
providers: [],
})
export class ServicesModule {
static forRoot(): ModuleWithProviders<ServicesModule> {
return {
ngModule: ServicesModule,
providers: [
all the services
provided in our application
]
}
}
}
// then in app.module.ts
imports: [
ServicesModule.forRoot(),
]
so my choices are
I guess a different/easier question is, if i move all my services back into the provider array of my app.module, would this simplify things? Seems counter intuitive.
If you put these all in a services module & import that in AppModule then it behaves the same as Injectable({ providedIn: 'root' })
. Which there's nothing wrong with marking a service as providedIn: 'root'
if it does need to be globally accessable, plus Angular will still lazy load in some way where an instance of that root-provided service will not be created if nothing ever injects it. The main thing is that there will be only one instance of the service created & shared between everything injecting it (unless you re-provide it in another module/component's providers
array).
For some things, that behavior is desireable. For instance if you have a user service that provides data about the currently signed in user, that would most likely be a service that's being used everywhere that only needs one instance created. So in that case, providedIn: 'root'
or providing it in AppModule
makes sense.
On the contrary, if you have a service that provides table data for a table component, then you would probably want that provided at the component level so that every individual instance of a table has access to its own data. If you provided this service at root, then every table would share the same data.
Usually what I do is either just provide the service in a component/module where it's needed or do providedIn: 'root'
if it needs to be singleton across the entire app.
You can also create small "atomic" modules where the module provides one service and then import that small module everywhere it's needed in order to allow for lazy loading.
For example:
@NgModule({
providers: [TestService]
})
export class TestModule { }
Then any module that has a component/directive/service/etc that needs to inject that service you would add TestModule
to the imports
array of the module that includes that component/directive/service/etc.
constructor(private testService: TestService) { }
@NgModule({
imports: [TestModule]
})
export class ModuleWithComponentThatNeedsTestService { }