首页 文章

在NgFor中添加动态组件

提问于
浏览
1

我想创建一个在参数中使用另一个组件的组件,并生成该组件的实例集合 .

(最终的目标是创建一个通用的后台) .

例如,有这样的东西:

<common-collection [component]="collectionDisplayComponent" [items]="items"></common-collection>

我会得到这个(这里的组件是一个用于测试目的的加载器):

enter image description here

所以我已经有了一些工作(差不多):这里是组件的代码:

@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()
      });
    }
}

并且模板代码关联:

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

这段代码有效,但问题是我在错误的时间设置了viewChildren,因为我有这个错误:

enter image description here

我想我应该填充widgetTargets变量并在其上执行ngFor而不是_items,但我没有找到任何直接在其中添加组件的示例 .

所有的例子都包括创建“void”dom元素,然后用组件工厂设置它们(我在那里做它并导致错误) .

非常感谢你的帮助 .

EDIT :"items"变量在组件init之后设置:它从异步调用加载到父组件中的数据库 .

EDIT2 在刷新方法中使用类似的东西 .

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

3 回答

  • 0

    试试这个:

    constructor(private cd: ChangeDetectorRef) {
    }
    
    ngAfterViewInit() {
       ......
        this.cd.detectChanges();
    }
    
  • 0

    你可以使用超时 .

    setTimeout(
      this.widgetTargets.changes.subscribe(() => {
        this.refresh()
      })
    ,0);
    
  • 1

    它将帮助您从typescript动态呈现组件

    var data=[{"cardStyle1":LineChartComponent},{"cardStyle2":BarChartComponent}]
       loadComponent(){ 
            for(var i=0;i<data.length;i++){
             const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.getComponentForCardType(data[i].name));
    
             let viewContainerRef = this.componentBind.viewContainerRef;
    
             const componentRef = viewContainerRef.createComponent(componentFactory);
             (<ImportcomponentComponent>componentRef.instance).datasource = this.datasourceData;
            }
    }
    

相关问题