Dynamically add components to ngFor

I have a “panel” that loads customized items. The dashboard template has the following:

  <div class="dash-container" [ngGrid]="gridConfig">
    <div *ngFor="let box of boxes; let i = index"
       [(ngGridItem)]="box.config"
       (onItemChange)="updateItem(i, $event)"
       (onResize)="onResize(i, $event)"
       (onDrag)="onDrag(i, $event)"
       (onDragStop)="onDragStop(i,$event)"
       [ngClass]="box.class"
     >
      <div class="handle"><h4>{{box.title}}</h4></div>
      <div [innerHTML]= "box.content"></div>
    </div>
  </div>

Now <div [innerHTML]= "box.content"></div>it will not work, because non-standard elements will be cleared. Launching the latest version of Angular 2.4.6 (RC 6).

I look at examples that I can find for dynamic components, but all I see is that they just add components to the current component, but I need them in very specific divs, as in the example above.

ComponentFactoryResolveroften used together with @ViewChild. But I can’t just do this inside the loop:

ngAfterViewInit() {
    const dashWidgetsConf = this.widgetConfigs();
    for (var i = 0; i < dashWidgetsConf.length; i++) {
      const conf = dashWidgetsConf[i];

      @ViewChild(conf.id, {read: ViewContainerRef}) var widgetTarget: ViewContainerRef;

      var widgetComponent = this.componentFactoryResolver.resolveComponentFactory(UnitsComponent);
      widgetTarget.createComponent(widgetComponent);
    }
  }

@viewchild " ". conf ( ) div (divs got #{{conf.id}}) ?

+10
3

( angular 4.0.0).

ViewContainerRef id:

@ViewChildren('dynamic', {read: ViewContainerRef}) public widgetTargets: QueryList<ViewContainerRef>;

, , factory createComponent.
, .

ngAfterViewInit() {
    const dashWidgetsConf = this.widgetConfigs();
    const widgetComponents = this.widgetComponents();
    for (let i = 0; i < this.widgetTargets.toArray().length; i++) {
        let conf = dashWidgetsConf[i];
        let component = widgetComponents[conf.id];
        if(component) {
            let target = this.widgetTargets.toArray()[i];
            let widgetComponent = this.componentFactoryResolver.resolveComponentFactory(component);
            let cmpRef: any = target.createComponent(widgetComponent);

            if (cmpRef.instance.hasOwnProperty('title')) {
                cmpRef.instance.title = conf.title;
            }
        }
    }
}

widgetComponents - {key: component}, widgetConfigs - , , ..

:

<div *ngFor="let box of boxes; let i = index" >
    <ng-template #dynamic></ng-template>
</div>

, conf (boxes ) - conf .

+19

if (cmpRef.instance.hasOwnProperty('title')) {
   cmpRef.instance.title = conf.title;
}

this.cd.detectChanges(); "ExpressionChangedAfterItHasBeenCheckedError: , " Angular 6x.

+1

:

<div *ngFor="for item in items">
  <!-- needs to be one per item -->
  <ng-template details-directive></ng-template>
</div>

:

@Component({
  selector: 'details-wrapper',
  template: '<ng-template details-directive></ng-template>'
})
export class DetailsWrapper {
  @Input item?: Item;
  // Dynamically load details using the regular solution.
}

:

<div *ngFor="for item in items">
  <details-wrapper [item]="item"></details-wrapper>
</div>
0

Source: https://habr.com/ru/post/1669925/


All Articles