1

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?

3 Answers 3

2

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;
        })
      }
Sign up to request clarification or add additional context in comments.

Comments

1

Have you tried using ngComponentOutlet

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

1 Comment

I have tried it but it isn't really helpful in this situation...the problem fixed by using trackBy inside ngFor loop...
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.