【问题标题】:How to use Output in dynamically created component如何在动态创建的组件中使用输出
【发布时间】:2017-02-03 10:36:09
【问题描述】:

我正在使用这种技术来动态创建组件:

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

然后我就这样使用它:

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

问题是我无法绑定到事件,绑定到(可见性)时它不起作用。事件发生时不会调用 setLayerVisibility。如何解决这个问题?

当然,我基于 componentClass 的示例组件的 @Output 设置如下:

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

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

【问题讨论】:

  • 问题还存在吗?

标签: angular typescript


【解决方案1】:

只需像这样订阅输出事件

@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();
}

在您的 html 文件中

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

【讨论】:

  • 我们在哪里订阅意味着将调用哪个生命周期钩子
【解决方案2】:

您的工厂:

factory.create(injector);

将返回一个 ComponentRef 对象,您可以使用该对象访问该组件本身。

您可以通过以下方式订阅该事件:

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

【讨论】:

  • 无法订阅未定义的。可能与组件生成的生命周期挂钩有关?
  • 回答自己:确实如此。只是,在 subscribe 的函数体中做一个 {outputs.emit(v)} 并且在也获取输入的函数中,也传递来自调用组件的输出
  • @yogibimbi 你能详细说明你的答案吗,每当我试图提供输出时,我都无法订阅 undefined 。我从指令加载动态组件。
  • 向我们展示你的代码,最好是一个小的 stackblitz.com
  • //这对我有用 :) component.instance.visibility.subscribe(v => ...);
猜你喜欢
  • 2021-04-22
  • 2012-10-03
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 2018-05-04
  • 1970-01-01
  • 1970-01-01
  • 2018-06-18
相关资源
最近更新 更多