Angular 2 How to make singleton service available to lazy loaded modules

前端 未结 2 633
[愿得一人]
[愿得一人] 2020-12-16 22:14

According to my understanding of Angular 2 rc5, to make a service from another module (not AppModule) available as a singleton to every component,

相关标签:
2条回答
  • 2020-12-16 22:42
    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 try adding LazyLoadedComponent to AppModule also, you would get an error to that effect. So LazyLoadedComponent is not even seeing MdIconModule at all. You can confirm this by looking at the template output in the debugger – it is unchanged.

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

    The solution appears to be adding the MdIconModule to the LazyModule, and while this alone does not fix the problem, it does add an error to the output.

    Error retrieving icon: Error: Unable to find icon with the name ":play"

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

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

    I added the call to addSvgIconSet from LazyLoadedComponent, and that got it working… so this proves there is an instance of the MdIconRegistry service per component – not what you want, but may point you in the right direction.

    Here’s the new plunk - http://plnkr.co/edit/YDyJYu?p=preview

    After further review, I found this in the docs:

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

    Unlike providers of the modules loaded at launch, providers of lazy loaded modules are module-scoped.

    Final Update! Here is the answer. MdIconModule is not properly setup for lazy loaded components... but we can easily create our own module that IS properly set up and use that instead.

    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 updated and fully working. (sorry, updated the same one) -> http://plnkr.co/edit/YDyJYu?p=preview

    One might submit a pull request such that Angular Material exports modules of both styles.

    0 讨论(0)
  • 2020-12-16 22:46

    New to Angular 6 there is a new way to register a provider as a singleton. Inside the @Injectable() decorator for a service, use the providedIn attribute. Set its value to 'root'. Then you won't need to add it to the providers list of the root module, or in this case you could also set it to your MdIconModuleWithProviders module like this:

    @Injectable({
      providedIn: MdIconModuleWithProviders // or 'root' for singleton
    })
    export class MdIconRegistry {
    ...
    
    0 讨论(0)
提交回复
热议问题