Search code examples
angulartypescriptobject-literal

Can an object literal have a component in its properties to be rendered by ngComponentOutlet?


I want to render each component using ngComponentOutlet in a certain column layout which I will style afterwards, but I'm getting null in the component property in this widgetsByCol, but I only have null in the html, because when doing the console.log() i see the component there. ( upon solving this problem, i want to render them dynamically, without defining the widgets the way I did )

This is the ts code:

export class WidgetListComponent implements OnInit {
  widgets: WidgetInterface[] = [
    { component: Test1Component, layoutCol: 1 },
    { component: Test2Component, layoutCol: 2 },
    { component: Test3Component, layoutCol: 3 },
    { component: Test3Component, layoutCol: 2 }
  ];

  widgetsByCol = {};

  ngOnInit(): void {
    for (const widget of this.widgets) {
      const { layoutCol, component } = widget;
      if (!this.widgetsByCol[layoutCol]) {
        this.widgetsByCol[layoutCol] = [];
      }
      this.widgetsByCol[layoutCol].push(component);
    }

    console.log('this.widgetsByCol', this.widgetsByCol);
  }
}

The html code:

{{widgetsByCol | json}}
<div *ngFor="let col of widgetsByCol | keyvalue">
  <div *ngFor="let widget of col.value">
    <ng-container *ngComponentOutlet="widget.component"> </ng-container>
  </div>
</div>

This {{widgetsByCol | json}} outputs: { "1": [ null ], "2": [ null, null ], "3": [ null ] } However the console.log outputs:

{
  1: [Test1Component],
  2: [Teste2Component, Teste3Component],
  3: [Test3Component]
}

So what's happening here ? Can someone help me out? Thanks in advance


Solution

  • Your code is very close to working. You have an error in the template where you refer to widget.component instead of simply widget.

    <ng-container *ngComponentOutlet="widget"></ng-container>
    

    The reason you see a difference between the console output and the json pipe output is because the json pipe stringifies your object. You will see the same result if you called called JSON.stringify() yourself:

    console.log('this.widgetsByCol (stringified)', JSON.stringify(this.widgetsByCol));
    // {"1":[null],"2":[null,null],"3":[null]}
    

    StackBlitz