List of different components in Angular 2 ngFor

I'd write another component, say item-flex:

<item-flex [item]="item" *ngFor="let item of items"></item-flex>

And item-flex could use either ngSwitch:

<div [ngSwitch]="item.type">
    <item-text *ngSwitchCase="'text'" [data]="item.data"></item-text>
    <item-image *ngSwitchCase="'image'" [data]="item.data"></item-image>
    <span *ngSwitchDefault >UNKNOWN TYPE:{{item.type}}</span>
</div>

or the "ugly ifs" (this way you can even get rid of the external tag/div/span that is present in ngSwitch solution):

<item-text *ngIf="item.type=='text'" [data]="item.data"></item-text>
<item-image *ngIf="item.type=='image'" [data]="item.data"></item-image>

My first thought would be to create a directive and use the Renderer class to add the appropriate component conditionally.

<div app-item [type]="item.type" [data]="item.data"></div>

Directive

import { Directive, ElementRef, Input, Renderer,  OnInit } from '@angular/core';

@Directive({
  selector: '[app-item]'
})
export class ItemDirective implements OnInit {
    @Input('type') type: string;
    @Input('data') data: any[];
    constructor(private el: ElementRef, private r: Renderer) {  }

    ngOnInit(): void {
        switch(this.type){
        case: 'text'
            let self = this.r.createElement( this.el.nativeElement, 'item-text' );
            this.r.setElementAttribute(self, 'data', 'this.data')
            break;
        case: 'image');
            let self = this.r.createElement( this.el.nativeElement, 'item-image'
            this.r.setElementAttribute(self, 'data', 'this.data')

            break;
        // ... so on ...
    }
}

You can use more @Inputs to pass in parameters and attach them using other Renderer methods.

This keeps the view very simple and will not not load modules for items whose tyoes ar not required.


This is my solution:

import { Component, OnInit, ViewContainerRef, TemplateRef, ComponentFactoryResolver, Input } from '@angular/core';

@Component({
  selector: 'item',
  template: '',
  styleUrls: ['./item.component.scss']
})
export class ItemComponent implements OnInit {
  @Input() type: string;
  @Input() data: any;

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

  ngOnInit() {
    const component = this.componentLookupService.findByType(type);
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
    // Look at the https://angular.io/docs/ts/latest/api/core/index/ViewContainerRef-class.html#!#createComponent-anchor for more information about how to use DI... in the createComponent function.
    const componentRef =this.viewContainerRef.createComponent(componentFactory);
    // Or you can then access the newly created component here: this.componentRef.instance
  }

}

In your NgFor loop:

<div *ngFor="let item of items">
   <item [type]="item.type" [data]="item.data"></item>
</div>

I guess you could use "ngComponentOutlet" that came with Angular 4 which creates component dynamically based on the value passed. I havent tested the code though.

@Component({
    selector: 'my-app',
    template: `
    <h1>Angular version 4</h1>
    <div *ngFor="let <component name> of <list of component name>">
        <ng-container *ngComponentOutlet="<component name>">enter code here</ng-container>
    </div>
  `,
})

please refer url for more details : https://netbasal.com/a-taste-from-angular-version-4-50be1c4f3550