Angular 2 How to make singleton service available for lazy loadable modules

According to my understanding of Angular 2 rc5 , in order to make a service from another module (not an AppModule ), available as a singleton for each component, even those that were loaded lazy, we do not include an array of this other module in the providers service. Instead, export it using RouterModule.forRoot() and import the result into AppModule

In accordance with the documents :

SharedModule should only provide a UserService when importing the root AppModule. The SharedModule.forRoot method helps us handle this call ... SharedModule has no providers ... When we add a SharedModule to import the AppModule, we call forRoot. In doing so, the AppModule receives the exported classes and the SharedModule provides a single-user UserService provider at the same time.

I am really struggling with how to make a third-party service (the service used by the module in the imports array of my AppModule ), available for lazy busy routes. I have no control over this third-party module, so I can’t just remove this service from the NgModule.providers array of this module and put it inside RouterModule.forRoot() , as with one of my services.

A specific MdIconRegistry service, which is located in providers for the MdIconModule of Angular Material 2 alpha 7-3 . This service is used to register svg icons, which can then be displayed on a page with the tag <md-icon svgIcon='iconName'> . So:

  • I imported MdIconModule to my AppModule root
  • I used this service to register svg icons in AppComponent

The icon displays and works well, but only in modules that were loaded at startup. Lazy-loaded modules cannot see these icons, so I suspect that the Angular injector is not injecting the same instance of the MdIconRegistry service.

tl; dr: How do I make a service from a third-party module available for my lazy components?

Here is the plunker demonstrating the problem (encoded in typescript ).

PS: It only got the attention of the MdIconModule developer on github.

+6
source share
1 answer
 I do not think it has anything to do with the component being lazy-loaded. 

LazyLoadedComponent is not part of the AppModule - it is part of the LazyModule. According to the docs, a component can only be part of one module. If you also try to add LazyLoadedComponent to the AppModule, you will receive an error message. Thus, LazyLoadedComponent does not even see the MdIconModule. You can confirm this by looking at the template output in the debugger - it has not changed.

 <md-icon svgIcon="play"></md-icon> 

The solution is similar to adding MdIconModule to LazyModule, and although this alone does not fix the problem, it adds an error to the output.

Error receiving icon: Error: Cannot find an icon with the name ": play"

And now the output of the template looks like this, so we know that it is loading.

 <md-icon role="img" svgicon="play" ng-reflect-svg-icon="play" aria-label="play"></md-icon> 

I added the addSvgIconSet call from LazyLoadedComponent and got it working ... so this proves that there is an instance of the MdIconRegistry service for each component - not what you want, but you can point it in the right direction.

Here is a new plot - http://plnkr.co/edit/YDyJYu?p=preview

After further review, I found this in docs :

Why is the service provided in a lazy loaded module visible only to that module?

Unlike suppliers of modules loaded at startup, suppliers of lazy loaded modules are modulated.

The final update! Here is the answer. MdIconModule is not configured correctly for lazy downloadable components ... but we can easily create our own module that is configured correctly and uses it.

 import { NgModule } from '@angular/core'; import { HttpModule } from '@angular/http'; import { MdIcon } from '@angular2-material/icon'; import { MdIconRegistry } from '@angular2-material/icon'; @NgModule({ imports: [HttpModule], exports: [MdIcon], declarations: [MdIcon] }) export class MdIconModuleWithProviders { static forRoot(): ModuleWithProviders { return { ngModule: MdIconModuleWithProviders, providers: [ MdIconRegistry ] }; } } 

Plunk is updated and fully operational. (sorry, updated the same) β†’ http://plnkr.co/edit/YDyJYu?p=preview

You can send a transfer request so that Angular Material exports modules of both styles.

+8
source

All Articles