EntryComponents in Module for LazyLoading

删除回忆录丶 提交于 2019-12-30 06:02:11

问题


I want to load a modal from a component. In Angular Material documentation is write to add the modal component in entryComponents :

This :

@NgModule({
  imports: [
    CommonModule,
    AidesRoutingModule
  ],
  declarations: [TypesAidesComponent, TypesAidesAjouterComponent],
  entryComponents : [TypesAidesAjouterComponent]
})
export class AidesModule {

}

In TypesAidesComponent I want open dialog with TypesAidesAjouterComponent :

let dialog = this.dialog.open(TypesAidesAjouterComponent);
    dialog.afterClosed().subscribe(res => {
      if(res){
        this.collection.addItem(res);
      }
    });

I'm in a component lazyloading :

{
        path: 'types-aides',
        loadChildren: 'app/modules/aides/aides.module#AidesModule'
    },

But I have this error :

Error: No component factory found for TypesAidesAjouterComponent. Did you add it to @NgModule.entryComponents?

I have found a solution, it is to move remove the LazyLoading but my application is large and is not a possibility.

Do you have any suggestions ?


回答1:


This is a common complaint with Angular at the moment. In certain instances, extracting a small component out of a lazy loaded module is not possible because of how dependency injection works. Components have to be brought into the application through their respective Module, which means if the module hasn't been loaded, you can't use any of the Components it declares.

I had to come to terms with the fact that there really are very few instances where this need arises in a well structured application, and that bumping up against it should be a sign that I needed to re-evaluate the structure of the application.

The best way to get around this issue is to extract the component and either create a separate module for it, or add it to a shared module that is imported into the module you are rendering it within.




回答2:


An alternative would be to use TemplateRef. This is especially useful in the case of the Angular Material dialog example above, which support both ComponentType and TemplateRef.

In the HTML, you can use @Input to pass your data to the component

<ng-template #popup>
  <my-component [data]="data"></my-component>
</ng-template>

The TS is very simple and there is no need to worry about the module to be lazy loaded or to use entryComponent.

@ViewChild("popup") popupRef: TemplateRef<any>;

public handleClick() {
  this.modalService.open(this.popupRef, options);
}



回答3:


So unfortunately this probably won't help you with the Angular Material dialog, but for anyone else running into the same issue with dynamically generated components in general, after running into the same issue when using my custom Modal component, and I developed an alternative solution: Passing the ComponentFactoryResolver I use in my custom modal service from the component that calls it.

So for example, let's say I have 2 components in a lazy loaded module: ModalContentComponent and CallerComponent.

In my CallerComponent, my constructor looks like this:

  constructor(
    private modalService: ModalService,
    private resolver: ComponentFactoryResolver,
  ) {}

And I call my modal service with:

this.modalService.open(ModalContentComponent, this.resolver);

And inside of my ModalService, if the resolver is provided in the open function, I use this passed resolver instead of the injected normally into my ModalService. This allows me to selectively provide my lazy loaded module's context as needed without having to restructure my entire application.



来源:https://stackoverflow.com/questions/48908746/entrycomponents-in-module-for-lazyloading

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!