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 component dynamically in to another component at runtime .
DynamicComponentHostDirective
In order to load a dynamic component you have to create a directive that you can apply to ng-template , which will helps to place 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: '[dynamiccomponent-host]',
})
export class DynamicComponentHostDirective {
constructor(public viewContainerRef: ViewContainerRef) {
}
}
ContainerComponent
This is just a place holder component to load the dynamic component.This component accepts an input(contains what component you want to load at runtime) 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 pass the dynamic component.
import { Component, Input, OnInit, AfterViewInit, ViewChild, ComponentFactoryResolver, OnDestroy } from '@angular/core';
import { DynamicComponentHostDirective } from './DynamicComponentHost.Directive;
import { YourInputDataModel } from './Data.Model';
import { DynamicComponentService } from "./DynamicComponent.Service";
@Component({
selector: 'container-component,
templateUrl: 'app/tile/ContainerComponent.Template.html'
})
export class ContainerComponent implements OnInit {
@Input() tile: any;
@ViewChild(DynamicComponentHostDirective ) componentHost: DynamicComponentHostDirective ;
constructor(private _componentFactoryResolver: ComponentFactoryResolver,private dynamicComponentService :DynamicComponentService ) {
}
ngOnInit() {
}
ngAfterViewInit() {
this.renderComponents();
}
renderComponents() {
let component=this.dynamicComponentService .getComponent(this.tile.componentName);
let componentFactory = this._componentFactoryResolver.resolveComponentFactory(component);
let viewContainerRef = this.componentHost.viewContainerRef;
let componentRef = viewContainerRef.createComponent(componentFactory);
(componentRef.instance).data = this.tile;
}
}
export interface YourInputDataModel {
data: any;
}
You can see I have applied the directive we have created before to the ng-template
ContainerComponent.Template.html
DynamicComponentService
This is a simple angular service factory to register the component you want to load at runtime.
@Injectable()
//register your component
export class DynamicComponentService {
getComponent(componentName:string) {
if(componentName==="YourDynamicComponent"){
return YourDynamicComponent
}
else if(componentName==="OtherComponent"){
return OtherComponent
}
}
}
YourDynamicComponent(Component we registered inside the factory loads dynamically )
import { Component, OnInit, Input, ReflectiveInjector, Injector } from '@angular/core';
@Component({
selector: 'mydynamiccomponent',
templateUrl: 'app/templates/YourDynamicComponent.html'
})
export class YourDynamicComponent implements OnInit {
@Input() data: any;
constructor() {
}
ngOnInit() {
}
}
Entry Component
Finally to ensure that the compiler still generates a factory, add dynamically loaded components to the NgModule’s entryComponents array. You can add this in to your app module
@NgModule({
imports: [BrowserModule,HttpModule],
providers: [DynamicComponentService],
declarations: [
YourDynamicComponent,
OtherComponent
],
exports: [],
entryComponents: [YourDynamicComponent,OtherComponent],
bootstrap: [MainApplicationComponent]
})
export class AppModule {
constructor() {
}
}
Source Code
Download Source
hello. I am looking for solution to embed html string that I get from API. The later string contains with material tags but it renders as simple divs. Can you help me? my post is here https://stackoverflow.com/q/45429888/8397456
Hi Jameel,
I am creating an application where I have to give login page first. If your provides valid credentials only then he will be able to view application. Can you suggest me what will be the best approach to do this?
hi does it has github respo as an example? thanks!
I didn’t upload yet..Once I am done I will let u
I’m also trying to set up a view that loads a bunch of tiles. I would love to see a mini solution where that was done, on github too. That would be much appreciated.
A small demo of this working, posted on github, would be awesome, and much appreciated.
I have uploaded the source code in Github(Link updated on my blog).
I have uploaded the source code in Github(Link updated on my blog).
Hi Can we use dynamic component with component inheritance.
Does it have impact on load ? as things works on browser , can it slowdown , i am trying widget based dashboard , want to use reusable components to do so
So far I didn’t faced any performance problem.We are not creating any components dynamically , load the components that’s physically available at run time.