I would like to create a component which takes another one in parameter, and generate a collection of instances of this component.
(The objective in the end is to create a generic backoffice).
For example, with something like that :
<common-collection [component]="collectionDisplayComponent" [items]="items"></common-collection> I would get this (here the component is a loader for test purpose) :
So I already have something working (almost): Here the code of the component :
@Component({ selector: 'common-collection', templateUrl: 'collection.component.html', styleUrls: ['collection.component.css'], providers: [ ] }) export class CollectionComponent implements AfterViewInit{ constructor(private componentFactoryResolver: ComponentFactoryResolver) { } @Input() set items(items: Array<object>){ this._items = items; this.refresh(); } private _items: Array<object> = [];screen @ViewChildren('componentRef', {read: ViewContainerRef}) public widgetTargets: QueryList<ViewContainerRef> public refresh() { let component = LoaderComponent; // Should be given in parameter, set manually for now if(typeof(this.widgetTargets) !== "undefined"){ for (let i = 0; i < this.widgetTargets.toArray().length; i++) { let target = this.widgetTargets.toArray()[i]; let widgetComponent = this.componentFactoryResolver.resolveComponentFactory(component); let cmpRef: any = target.createComponent(widgetComponent); } } } ngAfterViewInit(): void { this.widgetTargets.changes.subscribe(() => { this.refresh() }); } } And the template code associated :
<div id="div-container"> <div fxLayout="row" fxLayoutWrap fxLayoutGap="1%" fxFlexAlign="center center"> <div class="div-item-card" fxFlex="24" *ngFor="let item of _items;"> <div #componentRef></div> </div> </div> </div> This code works, but the problem is that I'm setting the viewChildren at the wrong time, because I have this error :
I think I should fill the widgetTargets variable and do the ngFor on it instead of _items, but I don't find any example to add components directly in it.
All the examples consist in creating "void" dom elements, and setting them with the component factory after that (which I do there and causes the error).
Thanks a lot for your help.
EDIT : The "items" variable is set after the component init : it is loaded from an async call to a database in a parent component.
EDIT2 Working with something like this in a refresh method.
for (let i = 0; i < this.widgetTargets.toArray().length; i++) { let target = this.widgetTargets.toArray()[i]; let widgetComponent = this.componentFactoryResolver.resolveComponentFactory(component); target.clear(); let cmpRef: any = target.createComponent(widgetComponent); cmpRef.instance.value = this._items[i]["value"]; this.cd.detectChanges(); } 

viewContainerRef.createComponent(componentFactory).changeDetectorRef.detectChanges()