Reputation: 1397
I am working on a project where I need to display a different template/component based on what my endpoint response is.
For example
{data: {type: 1, textToDisplay: 'I want beans'} }
Should inject Component 1 into the main app template.
If the data is
{data: {type: 2, textToDisplay: 'I want cheese', numberToDisplay: '101' } }
Should inject Component 2 into the main app template and of course Component 2 would be different to Component 1 because there's extra properties.
I really don't want to use bad practice by appending elements into the main app template nor do I want to write a massive template with [if]
directives as we could have many, 5-8, different components to render and it would bloat the template.
What's a suitable way?
Upvotes: 1
Views: 473
Reputation: 40647
As @Günter mentioned, you can use DynamicComponentLoader
@Component({
selector: 'my-app',
template: `<button (click)="addCmp()" #theBody>add</button>
`,
directives: [BaseDynamicComponent]
})
export class AppComponent {
@ViewChild('theBody', {read: ViewContainerRef}) theBody;
cmp:ComponentRef;
constructor(injector: Injector,private resolver: ComponentResolver) {}
addCmp(data){
console.log('adding');
this.resolver.resolveComponent(BaseDynamicComponent).then((factory:ComponentFactory<any>) => {
this.cmp = this.theBody.createComponent(factory);
//and you can set your BaseDynamicComponent's 'extra' properties here
this.cmp.instance.numberToDisplay = data.numberToDisplay;
});
}
}
This will add the BaseDynamicComponent under the #theBody element.
Here's an example plunkr:
If you click the add button it will add a new component with its test field assigned to "the test"
this.cmp.instance.test = "the test";
Or you can predefine the components like in @Günter's answer(https://stackoverflow.com/a/36325468/5706293) and then append them accordingly
Upvotes: 2