Создайте несколько разных динамических компонентов с помощью директивы ngFor Angular

#angular

#angular

Вопрос:

Я хотел бы вставить динамический список компонентов внутри шаблона родительского компонента, используя директиву ngFor для создания заполнителей узла ng-template для каждого компонента в списке. Что я пробовал:

шаблон компонента, в который будут вставлены динамические компоненты:

 <div *ngFor="let component of components;let i = index">
     <ng-template #dynamiccomponenthost></ng-template>
</div>
  

component.ts

  @Input()
components: any;

@ViewChildren('dynamiccomponenthost', { read: ViewContainerRef }) cHost: QueryList<ViewContainerRef>;

ngAfterViewInit() {
      this.loadComponents();
    }

private loadComponents(): void {
    this.cHost.map((vcr: ViewContainerRef, index: number) => {
      
        const factory = this.componentFactoryResolver.resolveComponentFactory(this.components[index].component);
       
        vcr.clear();

        vcr.createComponent(factory);
    });
  

входные данные ‘components’ представляют собой массив объектов, содержащих экземпляры динамических компонентов в следующей форме:

 [ 
   { 'component' : DynamicComponent1 },
   { 'component' : DynamicComponent2 }
]
  

С помощью *ngFor динамические компоненты не отображаются в DOM. Я также попытался создать узел-заполнитель ng-template, жестко закодированный внутри шаблона:

шаблон компонента:

 <div >
   <ng-template #kalasehost></ng-template>
 </div>
 <div >
   <ng-template #kalasehost></ng-template>
 </div>
  

С помощью этого шаблона разметки динамические шаблоны отображаются так, как ожидалось. Кто-нибудь может сказать мне, что я делаю неправильно, используя директиву ngFor?

Ответ №1:

Я решил эту проблему и написал статью на medium https://medium.com/@teslenkooleg2017/angular-13-create-multiple-dynamic-components-using-directive-ngfor-effe0850a69d

 //component.html
    <div *ngFor="let car of cars">
          <ng-template #dynamic></ng-template>
        </div>

// component.ts

 @ViewChildren('dynamic', {read: ViewContainerRef}) dynamic: QueryList<ViewContainerRef>;

    private loadComponent(): void {
        this.dynamic.map((vcr: ViewContainerRef, index: number) =>{
          vcr.clear();
          this.componentRef = vcr.createComponent(DynamicComponent);
          this.componentRef.instance.title = this.cars[index].title;
          this.componentRef.instance.text = this.cars[index].text;
        })
      }
  

Ответ №2:

Вы пробовали использовать ngComponentOutlet

 <div *ngFor="let component of components" [ngComponentOutlet]="component.component"></div>
  

Комментарии:

1. Я пробовал, но в этой ситуации это не очень полезно… проблема устранена с помощью trackBy внутри цикла ngFor…

Ответ №3:

Наконец, проблема решена с помощью trackBy внутри цикла *ngFor

component.html:

 <div *ngFor="let component of components;trackBy:identify;let i = index">
 <ng-template #dynamiccomponenthost></ng-template>
</div>
  

component.ts:

 identify(index, item) {
    return item amp;amp; item.id;
}