Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Output in dynamically created component

I am using this technique to dynamically create component:

import {  Component, Input, ViewContainerRef, ViewChild, ReflectiveInjector,    ComponentFactoryResolver,  Output, EventEmitter  } from '@angular/core';   @Component({  selector: 'dynamic-component',  template: `  <div #dynamicComponentContainer></div>  `,  })  export default class DynamicLayerComponent {  currentComponent = null;   @ViewChild('dynamicComponentContainer', { read: ViewContainerRef })     dynamicComponentContainer: ViewContainerRef;  @Output() visibility = new EventEmitter<boolean>();  // component: Class for the component you want to create // inputs: An object with key/value pairs mapped to input name/input value @Input() set componentData(data: {component: any, inputs: any }) { console.log('setting'); if (!data) {   return; }  // Inputs need to be in the following format to be resolved properly let inputProviders = Object.keys(data.inputs).map((inputName) => {return   {provide: inputName, useValue: data.inputs[inputName]};}); let resolvedInputs = ReflectiveInjector.resolve(inputProviders);  // We create an injector out of the data we want to pass down and this components injector let injector = ReflectiveInjector.fromResolvedProviders(resolvedInputs,    this.dynamicComponentContainer.parentInjector);  // We create a factory out of the component we want to create let factory = this.resolver.resolveComponentFactory(data.component);  // We create the component using the factory and the injector let component = factory.create(injector);  // We insert the component into the dom container this.dynamicComponentContainer.insert(component.hostView);  // We can destroy the old component is we like by calling destroy if (this.currentComponent) {   console.log('fdsafa');   this.currentComponent.destroy(); }  this.currentComponent = component; }   constructor(private resolver: ComponentFactoryResolver) {   console.log('dfsd');  } } 

And then I use it like that:

<div *ngFor="let layer of sortedItems" class="single-layer">   <div>     <dynamic-component #DynamicLayer                        [componentData]="{   component: layer.componentClass,   inputs: {     layerItem: layer,     sortFilter: sortFilter   } }"                        (visibility)="setLayerVisibility(layer, $event)">     </dynamic-component>   </div> 

The problem is that I am not able to bind to an event, it does not work when binding to (visibility). The setLayerVisibility is not called when the event occurs. How to fix that problem ?

Of course my sample component based on componentClass has the @Output set like:

  @Output() visibility = new EventEmitter<boolean>();  private visibilityChanged() {     this.visibility.emit(this.layerItem.visible);   } 
like image 379
Jerzy Gruszka Avatar asked Feb 03 '17 10:02

Jerzy Gruszka


2 Answers

Your factory:

factory.create(injector); 

will return an ComponentRef object, and with this object you can access that component itself.

You could subscribe to that event via:

component.instance.visibility.subscribe(v => ...); 
like image 184
slaesh Avatar answered Oct 23 '22 12:10

slaesh


Just subscribe the output event like this

@ViewChild('yourComponentRef', { read: ViewContainerRef }) container: ViewContainerRef; // Reference for dynamic component private _ref;  constructor( private _cfr: ComponentFactoryResolver){ }  public addDynamicComponent() {     const comp =         this._cfr.resolveComponentFactory(<YOUR_DYNAMIC_COMPONENT_HERE>);     this._ref = this.container.createComponent(comp);     // Input to dynamic component     this._ref.instance.inputVarHere = [1, 2, 3];     // Handles output event, just emit your output here     this._ref.instance.outputEventHere.subscribe(data => {         console.log(data);     }); } public removeDynamicComponent() {     this._ref.destroy(); } 

In your html file

<!-- Section to load dynamic component --> <div #yourComponentRef></div> 
like image 45
Aakash Purohit Avatar answered Oct 23 '22 12:10

Aakash Purohit