Angular 带有事件发射器的角度动态Html模板组件

Angular 带有事件发射器的角度动态Html模板组件,angular,angular-factory,angular-compiler,Angular,Angular Factory,Angular Compiler,我试图通过添加一个通用事件发射器来扩展这个组件的功能 import { Component, Directive, NgModule, Input, ViewContainerRef, Compiler, ComponentFactory, ModuleWithComponentFactories, ComponentRef, ReflectiveInjector } from '@angular/core'; import { RouterModule

我试图通过添加一个通用事件发射器来扩展这个组件的功能

import {
  Component,
  Directive,
  NgModule,
  Input,
  ViewContainerRef,
  Compiler,
  ComponentFactory,
  ModuleWithComponentFactories,
  ComponentRef,
  ReflectiveInjector
} from '@angular/core';

import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';

export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any>> {
  const cmpClass = class DynamicComponent { };
  const decoratedCmp = Component(metadata)(cmpClass);

  @NgModule({ imports: [CommonModule, RouterModule], declarations: [decoratedCmp] })
  class DynamicHtmlModule { }

  return compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule)
    .then((moduleWithComponentFactory: ModuleWithComponentFactories<any>) => {
      return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp);
    });
}

@Directive({ selector: 'html-outlet' })
export class HtmlOutlet {
  @Input() html: string;
  cmpRef: ComponentRef<any>;

  constructor(private vcRef: ViewContainerRef, private compiler: Compiler) { }

  ngOnChanges() {
    const html = this.html;
    if (!html) return;

    if (this.cmpRef) {
      this.cmpRef.destroy();
    }

    const compMetadata = new Component({
      selector: 'dynamic-html',
      template: this.html,
    });

    createComponentFactory(this.compiler, compMetadata)
      .then(factory => {
        const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
        this.cmpRef = this.vcRef.createComponent(factory, 0, injector, []);
      });
  }

  ngOnDestroy() {
    if (this.cmpRef) {
      this.cmpRef.destroy();
    }
  }
}
这告诉我,在componentFactory中创建函数时,函数没有正确地添加到类中


任何有棱角的大师,都能对我如何实现这一点给出一些见解?

设法将动态组件中的主题菊花链链接到html输出中的事件发射器,html输出的父级可以捕获该事件发射器

import {
  Component,
  Directive,
  NgModule,
  Input,
  ViewContainerRef,
  Compiler,
  ComponentFactory,
  ModuleWithComponentFactories,
  ComponentRef,
  ReflectiveInjector,
  EventEmitter,
  Output,


} from '@angular/core';
import { Observable, Subject } from 'rxjs'

import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { PartialObject } from 'lodash';

export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any>> {
  const cmpClass = class DynamicComponent {
    outputter: Subject<Object> = new Subject();
    genEmit(data) {
      this.outputter.next(data)
    }

  };
  const decoratedCmp = Component(metadata)(cmpClass);

  @NgModule({ imports: [CommonModule, RouterModule], declarations: [decoratedCmp] })
  class DynamicHtmlModule {

  }

  return compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule)
    .then((moduleWithComponentFactory: ModuleWithComponentFactories<any>) => {
      return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp);
    });
}

@Directive({ selector: 'html-outlet' })
export class HtmlOutlet {
  @Input() html: string;
  cmpRef: ComponentRef<any>;
  @Output() genericEmitter = new EventEmitter();


  constructor(private vcRef: ViewContainerRef, private compiler: Compiler) {

  }
  ngOnChanges() {
    const html = this.html;
    if (!html) return;

    if (this.cmpRef) {
      this.cmpRef.destroy();
    }

    const compMetadata = new Component({
      selector: 'dynamic-html',
      template: this.html,
    });

    createComponentFactory(this.compiler, compMetadata)
      .then(factory => {
        const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
        this.cmpRef = this.vcRef.createComponent(factory, 0, injector, []);
        this.cmpRef.instance.outputter.subscribe(v => {
          this.genericEmitter.emit(v)

        })



      });

  }

  ngOnDestroy() {
    if (this.cmpRef) {
      this.cmpRef.destroy();
    }
  }
}
导入{
组成部分,
指令,
NgModule,
输入,
ViewContainerRef,
编译程序,
组件工厂,
模块化组件工厂,
组件参考,
反射射束,
事件发射器,
产出,
}从“@angular/core”开始;
从“rxjs”导入{可观察,主题}
从'@angular/router'导入{RouterModule};
从“@angular/common”导入{CommonModule};
从“lodash”导入{PartialObject};
导出函数createComponentFactory(编译器:编译器,元数据:组件):承诺{
const cmpClass=类DynamicComponent{
输出:主题=新主题();
genEmit(数据){
this.outputter.next(数据)
}
};
const decoratedCmp=组件(元数据)(cmpClass);
@NgModule({imports:[CommonModule,RouterModule],声明:[decoratedCmp]})
类DynamicHtmlModule{
}
返回compiler.compileModule和AllComponentsAsync(DynamicHTML模块)
.然后((moduleWithComponentFactory:moduleWithComponentFactory)=>{
返回moduleWithComponentFactory.ComponentFactorys.find(x=>x.componentType===decoratedCmp);
});
}
@指令({selector:'html outlet'})
导出类HtmlOutlet{
@Input()html:string;
cmpRef:ComponentRef;
@Output()genericEmitter=neweventemitter();
构造函数(专用vcRef:ViewContainerRef,专用编译器:编译器){
}
ngOnChanges(){
const html=this.html;
如果(!html)返回;
if(this.cmpRef){
this.cmpRef.destroy();
}
const compMetadata=新组件({
选择器:“动态html”,
模板:this.html,
});
createComponentFactory(this.compiler,compMetadata)
。然后(工厂=>{
const injector=ReflectiveInjector.fromResolvedProviders([],this.vcRef.parentInjector);
this.cmpRef=this.vcreef.createComponent(工厂,0,注入器,[]);
this.cmpRef.instance.outputter.subscribe(v=>{
此.genericEmitter.emit(v)
})
});
}
恩贡德斯特罗(){
if(this.cmpRef){
this.cmpRef.destroy();
}
}
}

成功地将动态组件中的主题菊花链到html出口中的事件发射器,该事件发射器可由html出口的父级捕获

import {
  Component,
  Directive,
  NgModule,
  Input,
  ViewContainerRef,
  Compiler,
  ComponentFactory,
  ModuleWithComponentFactories,
  ComponentRef,
  ReflectiveInjector,
  EventEmitter,
  Output,


} from '@angular/core';
import { Observable, Subject } from 'rxjs'

import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { PartialObject } from 'lodash';

export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any>> {
  const cmpClass = class DynamicComponent {
    outputter: Subject<Object> = new Subject();
    genEmit(data) {
      this.outputter.next(data)
    }

  };
  const decoratedCmp = Component(metadata)(cmpClass);

  @NgModule({ imports: [CommonModule, RouterModule], declarations: [decoratedCmp] })
  class DynamicHtmlModule {

  }

  return compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule)
    .then((moduleWithComponentFactory: ModuleWithComponentFactories<any>) => {
      return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp);
    });
}

@Directive({ selector: 'html-outlet' })
export class HtmlOutlet {
  @Input() html: string;
  cmpRef: ComponentRef<any>;
  @Output() genericEmitter = new EventEmitter();


  constructor(private vcRef: ViewContainerRef, private compiler: Compiler) {

  }
  ngOnChanges() {
    const html = this.html;
    if (!html) return;

    if (this.cmpRef) {
      this.cmpRef.destroy();
    }

    const compMetadata = new Component({
      selector: 'dynamic-html',
      template: this.html,
    });

    createComponentFactory(this.compiler, compMetadata)
      .then(factory => {
        const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
        this.cmpRef = this.vcRef.createComponent(factory, 0, injector, []);
        this.cmpRef.instance.outputter.subscribe(v => {
          this.genericEmitter.emit(v)

        })



      });

  }

  ngOnDestroy() {
    if (this.cmpRef) {
      this.cmpRef.destroy();
    }
  }
}
导入{
组成部分,
指令,
NgModule,
输入,
ViewContainerRef,
编译程序,
组件工厂,
模块化组件工厂,
组件参考,
反射射束,
事件发射器,
产出,
}从“@angular/core”开始;
从“rxjs”导入{可观察,主题}
从'@angular/router'导入{RouterModule};
从“@angular/common”导入{CommonModule};
从“lodash”导入{PartialObject};
导出函数createComponentFactory(编译器:编译器,元数据:组件):承诺{
const cmpClass=类DynamicComponent{
输出:主题=新主题();
genEmit(数据){
this.outputter.next(数据)
}
};
const decoratedCmp=组件(元数据)(cmpClass);
@NgModule({imports:[CommonModule,RouterModule],声明:[decoratedCmp]})
类DynamicHtmlModule{
}
返回compiler.compileModule和AllComponentsAsync(DynamicHTML模块)
.然后((moduleWithComponentFactory:moduleWithComponentFactory)=>{
返回moduleWithComponentFactory.ComponentFactorys.find(x=>x.componentType===decoratedCmp);
});
}
@指令({selector:'html outlet'})
导出类HtmlOutlet{
@Input()html:string;
cmpRef:ComponentRef;
@Output()genericEmitter=neweventemitter();
构造函数(专用vcRef:ViewContainerRef,专用编译器:编译器){
}
ngOnChanges(){
const html=this.html;
如果(!html)返回;
if(this.cmpRef){
this.cmpRef.destroy();
}
const compMetadata=新组件({
选择器:“动态html”,
模板:this.html,
});
createComponentFactory(this.compiler,compMetadata)
。然后(工厂=>{
const injector=ReflectiveInjector.fromResolvedProviders([],this.vcRef.parentInjector);
this.cmpRef=this.vcreef.createComponent(工厂,0,注入器,[]);
this.cmpRef.instance.outputter.subscribe(v=>{
此.genericEmitter.emit(v)
})
});
}
恩贡德斯特罗(){
if(this.cmpRef){
this.cmpRef.destroy();
}
}
}
import {
  Component,
  Directive,
  NgModule,
  Input,
  ViewContainerRef,
  Compiler,
  ComponentFactory,
  ModuleWithComponentFactories,
  ComponentRef,
  ReflectiveInjector,
  EventEmitter,
  Output,


} from '@angular/core';
import { Observable, Subject } from 'rxjs'

import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { PartialObject } from 'lodash';

export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any>> {
  const cmpClass = class DynamicComponent {
    outputter: Subject<Object> = new Subject();
    genEmit(data) {
      this.outputter.next(data)
    }

  };
  const decoratedCmp = Component(metadata)(cmpClass);

  @NgModule({ imports: [CommonModule, RouterModule], declarations: [decoratedCmp] })
  class DynamicHtmlModule {

  }

  return compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule)
    .then((moduleWithComponentFactory: ModuleWithComponentFactories<any>) => {
      return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp);
    });
}

@Directive({ selector: 'html-outlet' })
export class HtmlOutlet {
  @Input() html: string;
  cmpRef: ComponentRef<any>;
  @Output() genericEmitter = new EventEmitter();


  constructor(private vcRef: ViewContainerRef, private compiler: Compiler) {

  }
  ngOnChanges() {
    const html = this.html;
    if (!html) return;

    if (this.cmpRef) {
      this.cmpRef.destroy();
    }

    const compMetadata = new Component({
      selector: 'dynamic-html',
      template: this.html,
    });

    createComponentFactory(this.compiler, compMetadata)
      .then(factory => {
        const injector = ReflectiveInjector.fromResolvedProviders([], this.vcRef.parentInjector);
        this.cmpRef = this.vcRef.createComponent(factory, 0, injector, []);
        this.cmpRef.instance.outputter.subscribe(v => {
          this.genericEmitter.emit(v)

        })



      });

  }

  ngOnDestroy() {
    if (this.cmpRef) {
      this.cmpRef.destroy();
    }
  }
}