Website-Suche

angular - Wie man Output in einer dynamisch erstellten Komponente verwendet


Ich verwende diese Technik, um dynamisch eine Komponente zu erstellen:

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');
 }
}

Und dann benutze ich es so:

<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>

Das Problem ist, dass ich nicht in der Lage bin, an ein Ereignis zu binden, es funktioniert nicht, wenn ich an (visibility) binde. Die Funktion setLayerVisibility wird nicht aufgerufen, wenn das Ereignis eintritt. Wie kann man dieses Problem beheben?

Natürlich hat meine beispielhafte Komponente basierend auf componentClass das @Output wie folgt gesetzt:

  @Output() visibility = new EventEmitter<boolean>();

private visibilityChanged() {
    this.visibility.emit(this.layerItem.visible);
  }

Antwort #1

Ihre Fabrik:

factory.create(injector);

wird ein ComponentRef-Objekt zurückgeben, und mit diesem Objekt können Sie auf diese Komponente selbst zugreifen.

Sie könnten sich über Folgendes für dieses Ereignis anmelden:

component.instance.visibility.subscribe(v => ...);

Antwort #2

Abonnieren Sie einfach das Ausgabeevent so

@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 Ihrer HTML-Datei

<!-- Section to load dynamic component -->
<div #yourComponentRef></div>

Verwandte Artikel