How do I provide a service in a lazy-loaded module and have that service scoped to just the lazy-loaded module and its components?

FlashBanistan picture FlashBanistan · Mar 17, 2017 · Viewed 11.7k times · Source

In the angular docs FAQ section it states, "Unlike providers of the modules loaded at launch, providers of lazy-loaded modules are module-scoped." link

Does 'module-scoped' here mean just the module or does it extend to include all components belonging to that module?

The reason I ask is because I have a lazy-loaded module with 2 components that belong to it. I register a service in the module but for some reason each component is getting a different instance of that service.

What do I need to change in order to provide LazyModuleService in my lazy-loaded module and have that service scoped to just the lazy-loaded module and it's components? Please include any additional files needed. I've tried to make a generic example to help anyone else who might find this question.

Lazy-loaded module:

import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { Component1 } from './component1.component';
import { Component2 } from './component2.component';
import { LazyModuleService } from './lazy-module.service';

@NgModule({
  imports: [
    CommonModule,
  ],
  declarations: [
    Component1,
    Component2,
  ],
})

export class LazyLoadedModule { }

Answer

snorkpete picture snorkpete · Mar 17, 2017

How lazy loading works:

After some deep investigation, it seems as though the problem is related to how lazy loading is implemented.

In your case, your lazy loaded module actually had routing to 2 different components within it - both of those components were directly exposed as Router.forChild routes. But, as a result, when you navigated to each component, a separate instance of your lazy loaded module's providers were added to each component.

Since you actually wanted all of the components in the lazy loaded module to share the same instance of their provided services, you need to create a single 'root' component and then have your two components be children of that root component.

It seems as though when lazy loading, the providers in your module will be added to the injector of the component at the root of your module. Since you have two 'root components', they each got separate instances of the services.

The solution was to create a single root component whose injector will receive the lazy loaded services, which can then be shared by any child components.