Angular Dynamic Components AOT Issue

安稳与你 提交于 2021-01-28 02:07:35

问题


Due to some business logic, I have to read the meta data of dynamic components(EntryComponents).

To read the meta data, following is my approach.

  1. Read all components of a module using ComponentFactoryResolver
  2. Filter out classes using Component name and specific method
  3. Create the component and read the data
  4. Destroy the component.

.

const factories = Array.from<any>(this.resolver['_factories'].keys());
console.log(factories); // Logging all the factories

factories.forEach(element => {
  if (element.prototype.registerReportCard) { // checking if this is dynamic component. Because dynamic component will have registerReportCard method in it
    temp.push(element.prototype.constructor.name); // if this is my dynamic component, push the name into another array "tmp".
  }
});

temp.forEach(componentName => { // stored component name from above
    const factoryClass = factories.find( // finding that component which have registerReportCard  method and has name same as iterator.
      item =>
        item.prototype.registerReportCard &&
        item.prototype.constructor.name === componentName
    );
    // component found, obviously.
    const component = this.resolver
      .resolveComponentFactory(factoryClass)
      .create(this.createInjector()); // creating the component and passing in the injector.

    console.log('component', component);

    const componentMeta = component.instance[
      'componentMeta'
    ] as ReportComponentMetaInterface; // Reading the DATA which i need.


    component.destroy(); // destroying the component after reading the data.
  });

createInjector() {
    const staticProvider = [{ provide: [], useValue: '' }];

    return Injector.create(staticProvider);
 }

THE PROBLEM

During development, factories names are working fine and are same as the dynamic component class.

But after building the project using ng build --prod. The factories names are as follows

As you can see, first im getting an error IDK where and why.

Secondly, the factories class names are same. Hence same dynamic component is being loaded 10 times (because there are 10 dynamic components).

Here is the NgModule

@NgModule({


 declarations: [
    DynamicComponentLoaderDirective,
    ContactsCreatedByDayComponent,
    ReportSkeletonComponent,
    SalesPerformanceComponent,
    TopPersonasComponent,
    ContactsOverviewComponent,
    CompaniesRevenueConversionComponent,
    ClosedCompaniesConversionComponent,
    AverageTimeCloseComponent,
    AverageTimeResponseComponent,
    ContactLifecyclePipelineComponent
  ],
  imports: [
    CommonModule,
    MatButtonModule,
    MatProgressSpinnerModule,
    ChartsModule
  ],
  entryComponents: [ContactsCreatedByDayComponent, SalesPerformanceComponent, TopPersonasComponent , ContactsOverviewComponent, CompaniesRevenueConversionComponent, ClosedCompaniesConversionComponent, AverageTimeCloseComponent, AverageTimeResponseComponent, ContactLifecyclePipelineComponent],
  exports: [DynamicComponentLoaderDirective, ReportSkeletonComponent, TopPersonasComponent, ContactsOverviewComponent, CompaniesRevenueConversionComponent, ClosedCompaniesConversionComponent, AverageTimeCloseComponent, AverageTimeResponseComponent, ContactLifecyclePipelineComponent],
  providers: [DashboardReportService]
})
export class DashboardSharedModule {}

I really dont know why is this happening. Can someone please put me in right direction?


回答1:


The --prod flag applies minification to your code which causes "...constructor.name" to end up as something like "a.name". This is the cause of your problem. The root problem is that your code won't work with minification and you should adapt it. You can configure your build not to optimize (angular.json in the current angular version), but minification has its sense, so you should try to find a way to provide the class name differently, e.g. with a string function param containing the name you can do that. Another implementation for passing data to entryComponents you can maybe compare at Angular Material, the MatDialogs are actually entryComponents which get MAT_DIALOG_DATA which you can specify in the way you want by injection: https://material.angular.io/components/dialog.



来源:https://stackoverflow.com/questions/56551008/angular-dynamic-components-aot-issue

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