Bhushan Gadekar Bhushan Gadekar - 7 months ago 241
Javascript Question

How to load multiple child components in angular2 using ngFor?

I have created few child components with given names using dynamic Component loader in angular2.
& I am able to load them using their selectors in static way.

for eg.
I can load my component using

<DYNAMIC-BODY-1>Loading</DYNAMIC-BODY-1>


But my problem is that these component names are stored in json file.
So I want to read that JSON File & load that component using its variable name.

for eg.
if
uiComponent="DYNAMIC-BODY-1";

then i should be able to load my component as
<{{uiComponent}}>Loading</{{uiComponent}}>


here is my html:

<div class="row">
<div *ngFor="#comp of record">
<div *ngFor="#pRow of comp.pageObj.pageRows">
<div *ngFor="#sec of pRow.sections">
<div *ngFor="#sRow of sec.sectionRows" class="col-md-{{(12/3)}}">
<div *ngFor="#srColumn of sRow.secRowColumns">
//prints component name i.e. DYNAMIC-BODY-1
{{srColumn.uiComponent}}
//Loads the component
<DYNAMIC-BODY-1>Loading</DYNAMIC-BODY-1>
//what I want to achieve,this does not work
<div [innerHTML]="'<' + srColumn.uiComponent+ '></' + srColumn.uiComponent + '>'"></div>
</div>
</div>
</div>
</div>
</div>
</div>


I tried multiple ways ,but I am not able to get the result.
Is there any way to do that?



import {Component,DynamicComponentLoader,Injector} from 'angular2/core';
import {NgSwitch, NgSwitchWhen, NgSwitchDefault,NgFor} from 'angular2/common';
import {Http, Response} from 'angular2/http';
import {Observable} from 'rxjs/Rx';
import { DataService } from '../../app/services/data.service';
import {DynamicBody1Component} from './../DYNAMIC-BODY-1/DYNAMIC-BODY-1.component'
import {DynamicBody2Component} from './../DYNAMIC-BODY-2/DYNAMIC-BODY-2.component'
import {FooterComponent} from './../FOOTER/FOOTER.component'
import {HeadingComponent} from './../heading/heading.component'
import {ImageComponent} from './../IMAGE/IMAGE.component'
import {StaticBodyComponent1} from './../STATIC-BODY-1/STATIC-BODY-1.component'
import {StaticBodyComponent2} from './../STATIC-BODY-2/STATIC-BODY-2.component'

@Component({
selector: 'Parser',
providers: [DataService],
templateUrl: 'app/Parser/Parser.component.html',
directives: [DynamicBody1Component, DynamicBody2Component, FooterComponent,HeadingComponent,ImageComponent,StaticBodyComponent1,StaticBodyComponent2]
})
export class ParserComponent {
public record;
public componentName;
public absolutePath;
constructor(dcl: DynamicComponentLoader, injector: Injector,private dataService: DataService) {

}
ngOnInit() {
this.componentName="Parser";
this.absolutePath="app/"+this.componentName+"/"+this.componentName+"-MODEL.json";
this.dataService.getData(this.absolutePath)
.subscribe((data:any[]) => {
this.record = data;
console.log(this.componentName);
});
}
subscribe({
complete: () => {setTimeOut(() => {
dcl.loadAsRoot(DynamicBody1Component, '#dynamic-body-1', injector);
dcl.loadAsRoot(DynamicBody2Component, '#dynamic-body-2', injector);
dcl.loadAsRoot(FooterComponent, '#footer', injector);
dcl.loadAsRoot(HeadingComponent, 'heading', injector);
dcl.loadAsRoot(ImageComponent, '#image', injector);
dcl.loadAsRoot(StaticBodyComponent1, '#static-body-1', injector);
dcl.loadAsRoot(StaticBodyComponent2, '#static-body-2', injector);
}, 1)});
}




Answer

You can't load components this way

<{{uiComponent}}>Loading</{{uiComponent}}>

You can't even create dynamic HTML this way. To create HTML you could

<div [innerHTML]="'<' + uiComponent + '></' + uiComponent + '>'"></div>

To dynamically add components you can use DynamicComponentLoader

You also can't have that dcl.loadAsRoot(...) code in the constructor. At this time the dynamically create HTML doesn't exist yet.
You can try to move that code to the

subscribe({/* process data - code omitted*/, 
    complete: () => {setTimeOut(() => {
    /* here the DOM should be rendered and dcl... should work */
    }, 1)});

to wait until the data arrived and than a bit more to give Angular time to render the DOM.

Comments