Angular 如何在动态创建的组件中使用输出

Angular 如何在动态创建的组件中使用输出,angular,typescript,Angular,Typescript,我正在使用此技术动态创建组件: import { Component, Input, ViewContainerRef, ViewChild, ReflectiveInjector, ComponentFactoryResolver, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'dynamic-component', template: ` <div #dynamicComp

我正在使用此技术动态创建组件:

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');
 }
}
导入{
组件、输入、ViewContainerRef、ViewChild、ReflectiveInjector、ComponentFactoryResolver、,
输出,事件发射器
}从“@angular/core”开始;
@组成部分({
选择器:“动态组件”,
模板:`
`,
})
导出默认类DynamicClayerComponent{
currentComponent=null;
@ViewChild('dynamicComponentContainer',{read:ViewContainerRef})dynamicComponentContainer:ViewContainerRef;
@Output()可见性=新的EventEmitter();
//component:要创建的组件的类
//输入:具有映射到输入名称/输入值的键/值对的对象
@Input()设置componentData(数据:{component:any,inputs:any}){
console.log('setting');
如果(!数据){
返回;
}
//输入需要采用以下格式才能正确解析
让inputProviders=Object.keys(data.inputName).map((inputName)=>{return{provide:inputName,useValue:data.inputName[inputName]};});
让resolvedInputs=ReflectiveInjector.resolve(inputProviders);
//我们用我们想要传递的数据创建一个注入器,这个注入器的组件
让injector=ReflectiveInjector.fromResolvedProviders(resolvedInputs,this.dynamicComponentContainer.parentInjector);
//我们用想要创建的组件创建一个工厂
让factory=this.resolver.resolveComponentFactory(data.component);
//我们使用工厂和喷油器创建部件
让组件=工厂创建(喷油器);
//我们将组件插入dom容器中
this.dynamicComponentContainer.insert(component.hostView);
//我们可以通过调用destroy来销毁旧组件
if(此.currentComponent){
console.log('fdsafa');
this.currentComponent.destroy();
}
this.currentComponent=组件;
}
构造函数(专用解析器: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);
  }
@Output()可见性=新的EventEmitter();
私有可视性更改(){
this.visibility.emit(this.layerItem.visible);
}
您的工厂:

工厂创建(喷油器);
将返回一个ComponentRef对象,使用此对象可以访问该组件本身

您可以通过以下方式订阅该活动:

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

只需像这样订阅输出事件

@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();
}
@ViewChild('yourComponentRef',{read:ViewContainerRef})容器:ViewContainerRef;
//动态组件的参考
私人(参考);
建造师(
私有{u cfr:ComponentFactoryResolver{}
public addDynamicComponent(){
康斯特公司=
这是。_cfr.resolveComponentFactory();
this.\u ref=this.container.createComponent(comp);
//动态组件的输入
这个._ref.instance.inputVarHere=[1,2,3];
//处理输出事件,只需在此处发出输出
此.\u ref.instance.outputEventHere.subscribe(数据=>{
控制台日志(数据);
});
}
公共removeDynamicComponent(){
这个._ref.destroy();
}
在html文件中

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


问题仍然存在?无法订阅未定义的。可能与组件生成的生命周期相关?对self的回答:是的。只是,在subscribe的函数体中做一个{outputs.emit(v)},在同样获取输入的函数中,也传递来自调用的输出component@yogibimbi你能详细说明一下你的答案吗?每当我试图给出输出时,我都无法订阅undefined。我从指令中加载动态组件。向我们展示您的代码,最好是一个小型stackblitz.com///this对我有用:)组件。实例。可见性。订阅(v=>…);我们订阅的位置意味着将调用哪个生命周期钩子