Have you seen the doc about dynamic component loading? It shows how you can dynamically insert components into the DOM.
More specifically, there are a few things you need to pay attention to:
1) Define an anchor point where the components will be inserted
You can do that with a template variable (#content
):
@Component({
template: `
<nav>...</nav>
<!-- This is where your components will be inserted -->
<div class="container" #content></div>
<footer>...</footer>
`
})
export class MyComponent {
@ViewChild('content', {read: ViewContainerRef}) content: ViewContainerRef;
constructor(private componentFactory: ComponentFactoryResolver) { }
ngAfterViewInit() {
this.loadComponents();
}
loadComponents() {
// Here, fetch the components from the backend
// and insert them at the anchor point.
}
}
2) Get the component CLASSES to insert and add them to the DOM
The problem is that your backend returns component names as strings, but ComponentFactoryResolver
expects classes.
You need to map component names to actual classes. You could use a custom object for this:
import {Widget1Component} from '../widget/widget1.component';
import {Widget2Component} from '../widget/widget2.component';
const componentsRegistry = {
'Widget1Component': Widget1Component
'Widget2Component': Widget2Component
};
Now the loadComponents()
method is easier to write:
loadComponents() {
// Fetch components to display from the backend.
const components = [
{ name: 'widget1', componentName: 'Widget1Component' },
{ name: 'widget2', componentName: 'Widget2Component' }
];
// Insert...
let componentClass, componentFactory;
for (let c of components) {
// Get the actual class for the current component.
componentClass = componentsRegistry[c.componentName];
// Get a factory for the current component.
componentFactory = this.componentFactory.resolveComponentFactory(componentClass);
// Insert the component at the anchor point.
this.content.createComponent(componentFactory);
}
}
3) Do not forget to add the dynamic components to entryComponents
Dynamically loaded components have to be added to their NgModule's entryComponents
array:
@NgModule({
// ...
entryComponents: [Widget1Component, Widget2Component, ...]
// ...
})
export class AppModule{ }