динамически визуализировать компонент в загруженном модуле с помощью AOT, не может найти фабрику компонентов - PullRequest
0 голосов
/ 23 октября 2018

Текущее поведение

Я объявил эти динамические компоненты как компоненты ввода в модуле, где я также хочу их визуализировать.С JIT все работает нормально.Следующая структура имеет часть моего приложения, я хочу их визуализировать: app -> home (lazy) -> contracts (lazy) -> search.

Поэтому я добавил эти компоненты в модуль, который я использую для search component/route.Когда я компилирую с AOT, каждый раз, когда я посещаю поисковый маршрут, приложение говорит мне, что нет фабрики компонентов.Конечно, я искал в Google и нашел некоторые результаты:

Я попытался добавить их к провайдеру ANALYZE_FOR_ENTRY_COMPONENTS, я попытался импортировать ModuleWithProviders с .forRoot() в моем app.module, а также я попытался просто импортировать и объявитьмоя динамика и все ее зависимые компоненты в корневом модуле (app.module).Все приводит к одной и той же ошибке.

Я объявляю свои динамические компоненты как компоненты ввода, например: <pre> @NgModule({ imports: [SharedComponentsModule, FinoSchemaFormsModule, TabGroupModule, FinoInputModule], declarations: [EnergySearchSettingsComponent, DslSearchSettingsComponent, MobileSearchSettingsComponent, ComparisonDetailSectionComponent], entryComponents: [EnergySearchSettingsComponent, DslSearchSettingsComponent, MobileSearchSettingsComponent], exports: [EnergySearchSettingsComponent, DslSearchSettingsComponent, MobileSearchSettingsComponent, ComparisonDetailSectionComponent], providers: [CategoryMappingProvider] }) export class ComparisonComponentsModule { }

Этот модуль импортируется в SearchModule, где также мой SearchComponent заявлено.В этом компоненте я хочу визуализировать эти компоненты динамически, используя ComponentFactoryResolver, который я вставляю в SearchComponent.

ngOnInit() {
    this.searchSettingsComponent = this.comparisonService.getSearchComponent(); // returns either EnergySearchSettingsComponent, DslSearchSettingsComponent or MobileSearchSettingsComponent
    let componentFactory = this.componentFactoryResolver.resolveComponentFactory(searchSettingsComponent);
    this.searchSettingsComponent = this.searchContainer.createComponent(componentFactory);
    this.searchSettingsComponent.instance.comparisonSettings = comparisonSettings;
    this.searchSettingsComponent.instance.onSave.subscribe(settings => this.saveSearchSettings(settings));
}

SearchComponent - это компонент маршрутизации маршрута search, который является дочерним маршрутом моего contract маршрута, который загружается отложенным образом.Это опять-таки дочерний маршрут моего домашнего маршрута (также загружен ленивым), и он относится к основному маршруту.

Environment

Angular version: 5.2.4

For Tooling issues:
- Node version: 8.11.3
- Platform:  Mac

Ответы [ 4 ]

0 голосов
/ 31 октября 2018

Создание общих модулей позволяет вам упорядочить и оптимизировать ваш код.Вы можете поместить часто используемые директивы, каналы и компоненты в один модуль, а затем импортировать только тот модуль, куда вам нужно, в другие части вашего приложения.

Повторным экспортом CommonModule и FormsModule, любого другого модуля, который импортируетэтот SharedModule получает доступ к директивам, таким как NgIf и NgFor, из CommonModule и может связываться со свойствами компонента с помощью [(ngModel)], директивы в FormsModule.

EX:

import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';

import { SharedModule } from '../../shared/shared.module';
import { EntryModalComponent  } from './entry-modal.component';

@NgModule({
 imports: [
   CommonModule,
   SharedModule,
   ReactiveFormsModule
 ],
declarations: [ EntryModalComponent ],
entryComponents: [ EntryModalComponent ],
exports: [ EntryModalComponent ]
})
export class EntryModalModule { }

Теперь вы можете использовать этот EntryModalComponent для динамической загрузки в какой-либо другой компонент после импорта модуля, в котором он определен.

0 голосов
/ 29 октября 2018

Я не чувствую, что в вашем вопросе достаточно информации, чтобы дать вам точный ответ на проблему, с которой вы сталкиваетесь.

Я смог найти решение с тем, что я считаюаналогично вашей настройке, которую вы могли бы использовать для решения вашей проблемы или для того, чтобы задать более острый вопрос.

TLDR: полное репозиторий GitHub здесь

Я создал структуру приложения каквыглядит следующим образом:

app/ app.module app.component /dynamic-provider --contains component that is dynamically loading other components --module is lazy loaded by dynamic-one module dynamic-loader.module slot.component /dynamic-one --contains lazy loaded module --module is lazy loaded by app module dynamic-one.module /dynamic-loader --contains a component to be dynamically loaded dynamic-provider.module one.component provider.service

app.module выглядит следующим образом

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    RouterModule.forRoot([
      { path: 'dynamic-loader', loadChildren: './dynamic-one/dynamic-one.module#DynamicOneModule' },
      { path: '', component: AppComponent }
    ])
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

dynamic-one.module выглядит следующим образом

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';

@NgModule({
  imports: [
    RouterModule.forChild([
      { path: '', loadChildren: '../dynamic-loader/dynamic-loader.module#DynamicLoaderModule' }
    ])
  ]
})
export class DynamicOneModule {
  constructor() {
    console.log('one');
  }
}

dynamic-loader.module выглядит следующим образом

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';

import { DynamicProviderModule } from '../dynamic-provider/dynamic-provider.module';

import { SlotComponent } from './slot.component';

@NgModule({
  declarations: [ SlotComponent ],
  imports: [
    DynamicProviderModule,
    RouterModule.forChild([
      { path: '', component: SlotComponent }
    ])
  ]
})
export class DynamicLoaderModule { }

dynamic-provider.module выглядит следующим образом

import { NgModule } from '@angular/core';

import { OneComponent } from './one.component';
import { ProviderService } from './provider.service';

@NgModule({
  declarations: [ OneComponent ],
  entryComponents: [ OneComponent ],
  exports: [ OneComponent ],
  providers: [ ProviderService ]
})
export class DynamicProviderModule { }

Как вы утверждаете, динамическое создание компонентов работает, когда модуль не работаетзагружен, так что я не включил этот код здесь (хотя он находится в репо для полноты).Однако, как можно увидеть здесь, модуль приложения лениво загружает модуль dynamic-one, который, в свою очередь, лениво загружает модуль динамического загрузчика.Модуль динамического загрузчика динамически создает компоненты из модуля динамического провайдера.

Чем это отличается от вашей реализации, очень трудно сказать, поскольку вы предоставили только небольшой объем информации.Я надеюсь, что это поможет вам найти недостающую часть, которую вы ищете, хотя!

0 голосов
/ 31 октября 2018

Вы пробовали обновить angular до последней версии 6.1.10?С версией 5 у меня были проблемы с лениво загруженными модулями.

У меня была похожая задача, и она работала нормально под 6.1.4.

Я создал рабочий пример для вас под 7.0.1

Я создал оба случая

  1. Динамический компонент объявлен в модуле, который создаст динамический компонент
  2. Динамический компонент объявлен в общем модуле и импортирован в lazy-загруженный модуль, который будет создавать динамические компоненты.Вы можете создать общий модуль для каждого динамического компонента, поэтому вы импортируете только один компонент в лениво загруженный модуль
0 голосов
/ 25 октября 2018

Это должно быть довольно просто.Просто создайте SharedModule и поместите в него все повторно используемые динамические компоненты, экспортируйте эти компоненты из SharedModule и импортируйте Module во все необходимые.Модули с отложенной загрузкой.

Поскольку он импортируется непосредственно в модуль, он должен быть доступен при создании динамического компонента.

...