Is there a way to make this possible in angular?
const arrayOfComponents = ['app-component-1', 'app-component-2', 'app-component-3']
<ng-container *ngFor="let component of arrayOfComponents">
<{{ component }} [data]="data"></{{ component }}>
</ng-container>
instead of:
<app-component-1 [data]="data"></app-component-1>
<app-component-2 [data]="data"></app-component-2>
<app-component-3 [data]="data"></app-component-3>
Because sometime we don't know the name of the component to view and the name is sent programmatically.
In other words I am trying to make a generic component which I send an array of component names/selectors to it and it renders them.
CodePudding user response:
You can achieve something simelar with a custom structural directive.
The Directive
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
interface IteratorContext<T> {
appTemplateIterator: T;
$implicit: T;
}
@Directive({
selector: '[appTemplateIterator]',
})
export class TemplateIteratorDirective<T> {
private context: IteratorContext<T> = {
appTemplateIterator: undefined,
$implicit: undefined,
};
private _templates: TemplateRef<IteratorContext<T>>[];
@Input()
set appTemplateIterator(value: T) {
this.context.appTemplateIterator = value;
this.context.$implicit = value;
this.updateView();
}
@Input()
set appTemplateIteratorFor(value: TemplateRef<IteratorContext<T>>[]) {
this._templates = value;
this.updateView();
}
constructor(private viewContainer: ViewContainerRef) {}
updateView() {
this.viewContainer.clear();
if (this.context.appTemplateIterator && this._templates) {
this._templates.forEach((template) =>
this.viewContainer.createEmbeddedView(template, this.context)
);
}
}
}
Usage
<ng-container
*appTemplateIterator="'Foobar'; for: [first, second]"
></ng-container>
<ng-template #first let-data>
<app-my-a [data]="data"></app-my-a>
</ng-template>
<ng-template #second let-data>
<app-my-b [data]="data"></app-my-b>
</ng-template>
Stackblitz: https://stackblitz.com/edit/angular-ivy-gbzkm4?file=src/app/app.component.html
CodePudding user response:
You can not use interpolation in place for HTML tags. Your best bet would be the Dynamic Component Loader