4

Suppose I have the following LazyModule that is lazily loaded and the LazyComponent declared inside of it:

@NgModule({
    declarations: [LazyComponent],
    providers: [LazyModuleService],
})
export class LazyModule { ...


@Component({
    selector: 'my-lazy',
    providers: [LazyComponentService]
})
export class LazyComponent { ...

My understanding is that when loading LazyModule angular will create a child injector for this module from rootInjector, something like this:

var lazyModuleInjector = rootInjector.resolveAndCreateChild([LazyModuleService]);

and then create a child injector for LazyComponent like this:

var lazyModuleInjector = lazyModuleInjector.resolveAndCreateChild([LazyComponentService]);

So eventually the injector tree be like this:

enter image description here

Is it correct?

Community
  • 1
  • 1
Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488

1 Answers1

6

Yes, this is correct. This wasn't done intentional but because an injector is readonly after it was created. Because lazy loaded modules are loaded later, its providers can't be added to the application root provider, because this one is already sealed. This is why they introduced a new root scope for lazy loaded modules.

If you want global providers (singletons) of providers provided by lazy loaded modules, implement forRoot() in the lazy loaded module and provide the global providers there, and then import only the providers into the application root scope with imports: [LazyModule.forRoot()].

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • thanks, _This is why they introduced a new root scope for lazy loaded modules._ - but basically it's not rootinjector in terms of the app, right? As I showed in my drawing, it's just a branch. And _implement forRoot() in the lazy loaded module_ - yeah, actually I can simply pass `{ngModule, providers}` object without implementing `forRoot` – Max Koretskyi Feb 16 '17 at 18:19
  • Yes, it's only the root for the lazy loaded part, but it is also a child injector to the app-root injector. (You could of course also argue, that it's not a root scope at all) – Günter Zöchbauer Feb 16 '17 at 18:20
  • yeah, thanks, just one clarification though, _its providers can't be added to the application root provider, because this one is already sealed_, I'm wondering if it's sealed, how can providers registered with `forRoot` added to it? – Max Koretskyi Feb 16 '17 at 19:19
  • 2
    Because they are added eagerly, not lazy. – Günter Zöchbauer Feb 16 '17 at 19:20
  • It is eagerly loaded because forRoot() is a static method which can be called without Instantiating the NgModule decorated class (when is being lazily loaded) . Right ? I am new to angular and just reading the documentation now :) – Rishav Mahapatra Jul 28 '20 at 06:19
  • @RishavMahapatra what do you mean by "It" (is eagerly loaded)? And why do you think it is eagerly loaded? The answer and question only talk about lazy loaded and how that introduces new scopes for the injector. – Günter Zöchbauer Jul 28 '20 at 10:24
  • I meant the "providers" are eagerly added to the root injector . In response to Max's comment saying " I'm wondering if it's sealed, how can providers registered with forRoot added to it" , and your subsequent comment saying "Because they are added eagerly, not lazy." – Rishav Mahapatra Jul 28 '20 at 12:23
  • @RishavMahapatra I think the Angular build tools are involved here as well and yes, the static forRoot allows it to evaluate the function with the providers eagerly, but without loading the whole module eagerly. – Günter Zöchbauer Jul 28 '20 at 16:28