Угловые динамические компоненты AOT Issue - PullRequest
0 голосов
/ 11 июня 2019

Из-за некоторой бизнес-логики мне приходится читать метаданные динамических компонентов (EntryComponents).

Чтобы прочитать метаданные, мой подход следующий.

  1. Чтение всех компонентов модуля с использованием ComponentFactoryResolver
  2. Отфильтровать классы, используя имя компонента и определенный метод
  3. Создание компонента и чтение данных
  4. Уничтожить компонент.

.

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);
 }

ПРОБЛЕМА

Во время разработки имена фабрик работают нормально и совпадают с классом динамических компонентов.

Но после сборки проекта с помощью ng build --prod. Названия заводов следующие enter image description here

Как видите, сначала я получаю сообщение об ошибке IDK, где и почему.

Во-вторых, имена классов заводов совпадают. Следовательно, один и тот же динамический компонент загружается 10 раз (поскольку имеется 10 динамических компонентов).

Вот модуль 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 {}

Я действительно не знаю, почему это происходит. Может кто-нибудь, пожалуйста, направить меня в правильном направлении?

1 Ответ

0 голосов
/ 12 июня 2019

Флаг --prod применяет минимизацию к вашему коду, что приводит к тому, что «... constructor.name» заканчивается как «a.name». Это причина вашей проблемы. Основная проблема в том, что ваш код не будет работать с минификацией, и вы должны его адаптировать. Вы можете настроить сборку так, чтобы она не оптимизировалась (angular.json в текущей угловой версии), но минимизация имеет смысл, поэтому вы должны попытаться найти способ предоставить имя класса по-другому, например, с помощью строковой функции param, содержащей имя, вы можете сделать это. Другая реализация для передачи данных в entryComponents, которую вы можете сравнить в Angular Material, на самом деле MatDialogs - это entryComponents, которые получают MAT_DIALOG_DATA, который вы можете указать нужным вам способом путем инъекции: https://material.angular.io/components/dialog.

...