Render Component Dynamically

20.9k views Asked by At

I have this array:

this.dashboard = [
     {name: '<app-incassi-provvigioni></app-incassi-provvigioni>'},
     {name: '<app-scheda-punti-vendita></app-scheda-punti-vendita>'}
]

I populate this array on the ngOnInit cycle. I was wondering how can I render the components when I read my array in the html like that:

<gridster [options]="gridsterOptions">
    <gridster-item [item]="item" *ngFor="let item of dashboard">
        <!-- your content here -->
        {{item.name}}
    </gridster-item>
</gridster>

Of course right now it returns the string contained in the object but I'm trying to find a solution to render the component. It is possible to do that?

More details: I am developing a dashboard type app where I retrieve the list of the user dashlet from the DB and I'm trying to render those components dynamically once the main app component is ready. using Angular 7 & Gridster2.

5

There are 5 answers

0
Igor Benić On

Maybe you can use an angular switch for this:

<div [ngSwitch]="item.name">
    <app-incassi-provvigioni *ngSwitchCase="incassi"></app-incassi-provvigioni>
    <app-scheda-punti-vendita *ngSwitchCase="scheda"></app-scheda-punti-vendita>
</div>
3
indsoft On

rather passing component tag name("app-incassi-provvigioni" in your case), pass the component name (TestComponenet), then call the function from your view and render it as dynamically with Directive.

eg:

<gridster [options]="gridsterOptions">
  <gridster-item [item]="item" *ngFor="let item of dashboard">
    <div class="inner">
      <ng-template dynamic-template> </ng-template>
    </div>
  </gridster-item>
</gridster>

dynamic-template is a directive, that help us to load the component.

0
Syam Prasad On
this.dashboard = [
         {name: 'dashboard1'},
         {name: 'dashboard2'}
    ]

    <gridster [options]="gridsterOptions">
        <gridster-item [item]="item" *ngFor="let item of dashboard">
            <ng-container *ngIf="item.name === 'dashboard1'" *ngTemplateOutlet="dashboard1">
            </ng-container>
            <ng-container *ngIf="item.name === 'dashboard1'" *ngTemplateOutlet="dashboard2">
            </ng-container>
        </gridster-item>
    </gridster>


    <ng-template #dashboard1>
        <app-incassi-provvigioni></app-incassi-provvigioni>
    </ng-template>
    <ng-template #dashboard2>
        <app-scheda-punti-vendita></app-scheda-punti-vendita>
    </ng-template>
1
NechiK On

You can inject component dynamically

Just create component with @Input() component;

export class DynamicContentComponent implements OnInit {

  @Input() component: any;
  @Input() data: any;

  constructor(public viewContainerRef: ViewContainerRef,
              private componentFactoryResolver: ComponentFactoryResolver) { }

  ngOnInit() {
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.component);
    this.viewContainerRef.clear();

    const componentRef = this.viewContainerRef.createComponent(componentFactory);
    (<DynamicComponentRef>componentRef.instance).data = this.data;
  }
}

And use it in HTML

<app-dynamic-content [component]="someComponent" [data]="data"></app-dynamic-content>

Data example

someComponent = SchedaPuntiVendita;

Dynamic components should be added to entryComponents in your module

Also you can create some kind of factory which will receive some string and depends on it returns you component class

Factory example

@Injectable()
export class DynamicContentComponentFactory {

  constructor() { }

  get(type: ContentType): any {
    switch (type) {
      case 'scheda':
        return SchedaPuntiVendita;
    }
  }

And modify DynamicContentComponent a little

@Input() contentType: string;

constructor(..., private factory: DynamicContentComponentFactory) { }
...

const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.factory.get(this.contentType));

...
0
Dimitar Stojanovski On

if you are using gridster2, actually there is reference so you could use npm package as https://www.npmjs.com/package/ng-dynamic-component .

Here is an example of my code:

 <gridster-item
      class="gridster-item"
      [item]="item.gridItem"
      *ngFor="let item of dashboard; let i = index"
      (itemResize)="getItemSize($event, i)"
    >
      <button class="button-remove-item" (click)="removeItem(item)">
        <img src="assets/remove-item.svg" />
      </button>
      <div class="gridster-item-inner">
        <ndc-dynamic
          [ndcDynamicInputs]="item.size"
          [ndcDynamicComponent]="item.component.data"
        ></ndc-dynamic>
      </div>
    </gridster-item>

Let me know if you have any issues.