Angular 动态 Html 带有事件发射器的模板组件
Angular Dynamic Html Template component with event emitter
我正在尝试通过添加通用事件发射器来扩展此组件的功能
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();
}
}
}
鸣谢原作者
https://gist.github.com/benjamincharity/8116414c7f38cffe3cef0e44fe44295d
所需事件的示例
@Output() genericEventEmitter = new EventEmitter<string>();
emitEvent(data:string){
this.genericEventEmitter.emit(data)
}
我已经尝试将其添加到 htmlOutlet class 以及 DynamicComponent 我收到了错误消息
ERROR TypeError: _co.emitEvent is not a function
at Object.eval [as handleEvent] (DynamicComponent.html:6)
这告诉我,当在 componentFactory
中创建函数时,该函数没有正确添加到 class
任何 Angular 专家,能否就我如何使它起作用提供一些见解?
设法以菊花链方式将动态组件中的主题链接到 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();
}
}
}
我正在尝试通过添加通用事件发射器来扩展此组件的功能
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();
}
}
}
鸣谢原作者 https://gist.github.com/benjamincharity/8116414c7f38cffe3cef0e44fe44295d
所需事件的示例
@Output() genericEventEmitter = new EventEmitter<string>();
emitEvent(data:string){
this.genericEventEmitter.emit(data)
}
我已经尝试将其添加到 htmlOutlet class 以及 DynamicComponent 我收到了错误消息
ERROR TypeError: _co.emitEvent is not a function
at Object.eval [as handleEvent] (DynamicComponent.html:6)
这告诉我,当在 componentFactory
中创建函数时,该函数没有正确添加到 class任何 Angular 专家,能否就我如何使它起作用提供一些见解?
设法以菊花链方式将动态组件中的主题链接到 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();
}
}
}