'Create multiple different dynamic components using ngFor directive Angular

I would like to insert a dynamic list of components inside parent component template using ngFor directive to create ng-template host placeholders for each component in the list. What I have tried:

component template where dynamic components will be inserted:

<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' input is an array of objects containing the dynamic component instances in the following form:

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

Using *ngFor the dynamic components are not rendered in the DOM. I have tried also to create ng-template placeholder host hardcoded inside the template:

component template:

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

Using this template markup dynamic templates are rendered as expected. Could anyone tell me what I am doing wrong using ngFor directive?



Solution 1:[1]

Have you tried using ngComponentOutlet

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

Solution 2:[2]

Finally, the provblem solved by using trackBy inside *ngFor loop

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 && item.id;
}

Solution 3:[3]

I solved this problem and write an article on 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;
        })
      }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Poul Kruijt
Solution 2 tsiro
Solution 3