Load Components Dynamically at runtime in Angular 4

Angular Version I have used – 4.2.0
Here I am going to explain how to load dynamic components at runtime. By using angular ComponentFactoryResolver you can load components dynamically. In the below example I am loading a Image widgets in to tile(nothing but a container div to load the widget at runtime). You can use this to in order to implement the need of $compile in Angular 1.0

WidgetHostDirective
In order to load a dynamic component you need a directive that you can apply to ng-template which will helps to load the components at run time. This directive injects ViewContainerRef to gain access to the view container of the element that will host the dynamically added component.

import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[widget-host]',
})
export class DashboardTileWidgetHostDirective {
constructor(public viewContainerRef: ViewContainerRef) {
}
}

DashboardTileComponent
This component accepts an input which is coming from a parent components or you can load from your service based on your implementation. This component is doing the major role to resolve the components at runtime. In this method you can also see a method named renderComponent() which ultimately loads the component name from a service and resolve with ComponentFactoryResolver and finally setting data to the dynamic component.
import { Component, Input, OnInit, AfterViewInit, ViewChild, ComponentFactoryResolver, OnDestroy } from '@angular/core';
import { DashboardTileWidgetHostDirective } from './DashbardWidgetHost.Directive';
import { TileModel } from './Tile.Model';
import { WidgetComponentService } from "./WidgetComponent.Service";
@Component({
selector: 'dashboard-tile',
templateUrl: 'app/tile/DashboardTile.Template.html'
})
export class DashboardTileComponent implements OnInit {
@Input() tile: any;
@ViewChild(DashboardTileWidgetHostDirective) widgetHost: DashboardTileWidgetHostDirective;
constructor(private _componentFactoryResolver: ComponentFactoryResolver,private widgetComponentService:WidgetComponentService) {

}
ngOnInit() {

}
ngAfterViewInit() {
this.renderComponents();
}
renderComponents() {
let component=this.widgetComponentService.getComponent(this.tile.componentName);
let componentFactory = this._componentFactoryResolver.resolveComponentFactory(component);
let viewContainerRef = this.widgetHost.viewContainerRef;
let componentRef = viewContainerRef.createComponent(componentFactory);
(componentRef.instance).data = this.tile;

}
}
export interface TileModel {
data: any;
}

You can see I have applied the directive we have created before to the ng-template
DashboardTileComponent Template

WidgetComponentService
This is a simple angular service which just the component name that we want to load at runtime

Entry Component
To ensure that the compiler still generates a factory, add dynamically loaded components to the NgModule’s entryComponents array

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s