返回的html上的Angular 2+ onmouseover事件

时间:2018-10-16 16:26:41

标签: javascript angular typescript

您好,我的component.ts中有一个返回如下html的方法:

someMethod() {
    return `
      <div>hello</div>
    `;
}

我想返回一个带有mouseover事件的div,但是(mouseenter)="myFunction()"的角度方式似乎不起作用。可能是因为它返回的是html并且未编译。

someMethod() {
    return `
      <div (mouseenter)="myFunction()">hello</div>
    `;
}

因此,我发现以常规JavaScript方法onmouseover="myFunction()"确实会触发该函数:

someMethod() {
    return `
      <div onmouseover="myFunction()">hello</div>
    `;
}

但是问题在于,我收到了错误Uncaught ReferenceError: myFunction is not defined

myFunction()是与component.ts在同一someMethod()文件中的方法,该方法返回html

任何人都可以帮助我解决我的问题,或者建议另一种写此方法的方法吗?

谢谢

2 个答案:

答案 0 :(得分:3)

您的要求是呈现Angular html模板,该模板将用作字符串值(它可能来自DB)。

坏消息

这不是您现在的方式。仅从ts文件绑定到html中获取字符串值是行不通的,因为Angular绑定时不会编译模板。

好消息

虽然可以在Angular中实现,但不是一种简单的方法。如果您真的想实现此功能并广泛使用,那么绝对值得花一些时间。

这里是RuntimeContentComponent,可帮助编译Angular模板

runtime-content.component.ts

import { 
    Component,
    ViewChild, ViewContainerRef, ComponentRef,
    Compiler, ComponentFactory, NgModule, ModuleWithComponentFactories, ComponentFactoryResolver
} from '@angular/core';

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

@Component({
    selector: 'runtime-content',
    template: `
        <div>
            <h3>Template</h3>
            <div>
                <textarea rows="5" [(ngModel)]="template"></textarea>
            </div>
            <button (click)="compileTemplate()">Compile</button>
            <h3>Output</h3>
            <div #container></div>
        </div>
    `
})
export class RuntimeContentComponent {

    template: string = '<div>\nHello, {{name}}\n</div>';

    @ViewChild('container', { read: ViewContainerRef })
    container: ViewContainerRef;

    private componentRef: ComponentRef<{}>;

    constructor(
        private componentFactoryResolver: ComponentFactoryResolver,
        private compiler: Compiler) {
    }

    compileTemplate() {

        let metadata = {
            selector: `runtime-component-sample`,
            template: this.template
        };

        let factory = this.createComponentFactorySync(this.compiler, metadata, null);

        if (this.componentRef) {
            this.componentRef.destroy();
            this.componentRef = null;
        }
        this.componentRef = this.container.createComponent(factory);
    }

    private createComponentFactorySync(compiler: Compiler, metadata: Component, componentClass: any): ComponentFactory<any> {
        const cmpClass = componentClass || class RuntimeComponent { name: string = 'Denys' };
        const decoratedCmp = Component(metadata)(cmpClass);

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

        let module: ModuleWithComponentFactories<any> = compiler.compileModuleAndAllComponentsSync(RuntimeComponentModule);
        return module.componentFactories.find(f => f.componentType === decoratedCmp);
    }

}

链接

请参阅这篇出色的文章以获取完整的详细信息-https://medium.com/@DenysVuika/dynamic-content-in-angular-2-3c85023d9c36

答案 1 :(得分:1)

Angular (event)无法正常工作,因为模板不是由angular编译的,据我所知,这是不可能的。在构建项目之前,您必须为此定义组件或指令。另一种方法比较难,但是可以解决问题

您应该首先“ compile” html字符串,然后通过抓取特定元素并使用addEventListener将其绑定。

someMethod() {
    const stringifiedHTML = `
      <div onmouseover="myFunction()">hello</div>
    `;
    // create an empty div that will hold
    // stringified html and convert it to actual tree
    const div = document.createElement('div'); 
    // this will convert stringifiedHTML to acutal node tree
    div.innerHTML = stringifiedHTML;
    const resultHTML = div.firstElementChild;
    // now find exactly element you want to bind and do it with addEventListener
}