I instantiated dynamic components by selecting existing components. For instance,
@Component({ selector: 'dynamic-component', template: `<div #container><ng-content></ng-content></div>` }) export class DynamicComponent { @ViewChild('container', {read: ViewContainerRef}) container: ViewContainerRef; public addComponent(ngItem: Type<WidgetComponent>,selectedPlugin:Plugin): WidgetComponent { let factory = this.compFactoryResolver.resolveComponentFactory(ngItem); const ref = this.container.createComponent(factory); const newItem: WidgetComponent = ref.instance; newItem.pluginId = Math.random() + ''; newItem.plugin = selectedPlugin; this._elements.push(newItem); return newItem; } }
My predefined components are ChartWidget and PatientWidget, which extended the WidgetComponent class that I wanted to add to the container. For instance,
@Component({ selector: 'chart-widget', templateUrl: 'chart-widget.component.html', providers: [{provide: WidgetComponent, useExisting: forwardRef(() => ChartWidget) }] }) export class ChartWidget extends WidgetComponent implements OnInit { constructor(ngEl: ElementRef, renderer: Renderer) { super(ngEl, renderer); } ngOnInit() {} close(){ console.log('close'); } refresh(){ console.log('refresh'); } ... }
chart-widget.compoment.html (using the primeng panel)
<p-panel [style]="{'margin-bottom':'20px'}"> <p-header> <div class="ui-helper-clearfix"> <span class="ui-panel-title" style="font-size:14px;display:inline-block;margin-top:2px">Chart Widget</span> <div class="ui-toolbar-group-right"> <button pButton type="button" icon="fa-window-minimize" (click)="minimize()"</button> <button pButton type="button" icon="fa-refresh" (click)="refresh()"></button> <button pButton type="button" icon="fa-expand" (click)="expand()" ></button> <button pButton type="button" (click)="close()" icon="fa-window-close"></button> </div> </div> </p-header> some data </p-panel>
data-widget.compoment.html (same as chart widget using primeng panel)
@Component({ selector: 'data-widget', templateUrl: 'data-widget.component.html', providers: [{provide: WidgetComponent, useExisting: forwardRef(() =>DataWidget) }] }) export class DataWidget extends WidgetComponent implements OnInit { constructor(ngEl: ElementRef, renderer: Renderer) { super(ngEl, renderer); } ngOnInit() {} close(){ console.log('close'); } refresh(){ console.log('refresh'); } ... }
WidgetComponent.ts
@Component({ selector: 'widget', template: '<ng-content></ng-content>' }) export class WidgetComponent{ }
Now I added components by selecting a component from existing components (for example, a chart widget and a data widget) as follows and saved the instances in an array.
@Component({ templateUrl: 'main.component.html', entryComponents: [ChartWidget, DataWidget], }) export class MainComponent implements OnInit { private elements: Array<WidgetComponent>=[]; private WidgetClasses = { 'ChartWidget': ChartWidget, 'DataWidget': DataWidget } @ViewChild(DynamicComponent) dynamicComponent: DynamicComponent; addComponent(): void{ let ref= this.dynamicComponent.addComponent(this.WidgetClasses[this.selectedComponent], this.selectedComponent); this.elements.push(ref); this.dynamicComponent.resetContainer(); } }
Now I am facing the problem of rendering components with innerHtml in main.component.html. It displays html, but I cannot use the button click event or another event on it. I also tried to display the chart using primeng, but it also does not work.
main.component.html
<dynamic-component [hidden]="true" ></dynamic-component> <widget *ngFor="let item of elements"> <div [innerHTML]="item._ngEl.nativeElement.innerHTML | sanitizeHtml"> </div> </widget>
I also implemented sanitizeHtml Pipe, but it gave the same result. So, as far as I understand, innerHtml only shows html data, but I can not use any button event, as well as js chart. I also tried showing items like this {{item}} under the tag. But it is displayed as text [object object]. So can anyone give a solution? How can I visualize components allowing button events and js chart? Thanks.
EDIT: See my Plunker here https://plnkr.co/edit/lugU2pPsSBd3XhPHiUP1?p=preview Here you can see the diagram or data speaker dynamically, and I am showing it using innerHTML. Thus, button events do not work here. If I encode as {{item}} then it shows the text [object object]. You can also see component array data in the console. The main question: How can I activate button events on it (for example, if I click the close or update button, then it will call related functions)?