If you need a function that can create dynamic components on the fly, you can use the following generic function.
public createDynamicComponent<T>(component: Type<T>, viewRef: ViewContainerRef): ComponentRef<T> {
const factory = this.cfr.resolveComponentFactory<T>(component);
return viewRef.createComponent(factory);
}
When calling the generic function, make sure to specify the component type and the ViewContainerRef.
this.createDynamicComponent<DynamicComponent>(DynamicComponent, this.vc /* ViewContainerRef */);
For a working example, check out this Stackblitz example app.
Note: Remember to include dynamic components in the entryComponents
array in the module file.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { DynamicComponent } from './dynamic.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent, DynamicComponent ],
entryComponents: [DynamicComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Full Component Context
import {
AfterViewInit, Component, ComponentFactoryResolver, ComponentRef, Type, ViewChild, ViewContainerRef
} from '@angular/core'
import { DynamicComponent } from './dynamic.component'
@Component({
selector: 'my-app',
template: `
<h1>App component</h1>
<div class="insert-dynamic-component">
<ng-container #vc></ng-container>
</div>
`,
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements AfterViewInit {
@ViewChild('vc', {read: ViewContainerRef, static: false}) vc: ViewContainerRef;
public constructor(private cfr: ComponentFactoryResolver) {}
ngAfterViewInit() {
// setTimeout() to prevent error "Expression has changed after it was checked"
// See: https://blog.angular-university.io/angular-debugging/
setTimeout(() => {
const componentRef: ComponentRef<DynamicComponent> =
this.createDynamicComponent<DynamicComponent>(DynamicComponent, this.vc);
componentRef.instance.data = 'New data';
});
}
public createDynamicComponent<T>(component: Type<T>, viewRef: ViewContainerRef): ComponentRef<T> {
const factory = this.cfr.resolveComponentFactory<T>(component);
return viewRef.createComponent(factory);
}
}
DynamicComponent
import { Component } from '@angular/core';
@Component({
selector: 'dynamic-component',
template: `<h1>Dynamic Component!</h1>
<p>Data: {{data}}</p>`,
styles: [`h1 { font-family: Lato; }`]
})
export class DynamicComponent {
public data: any
}