【问题标题】:Dynamic Component Click event Binding - Angular 2动态组件点击事件绑定 - Angular 2
【发布时间】:2018-02-02 01:08:51
【问题描述】:

有可能重复,但我的情况有点不同。

我想为我的动态组件执行点击事件。

这是我的结构:

     <razor>
          <mvc-partial>
            <dynamic-html> // buttonPress(){console.log("Function called in dynamicHtml)
                          // Output() to call function in razor.ts
            </dynamic-html>
          </mvc-partial>
      <razor>

RenderingViewDynamic.ts 文件

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

import { RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { Http } from "@angular/http";
import 'rxjs/add/operator/map';

export function createComponentFactory(compiler: Compiler, metadata: Component): Promise<ComponentFactory<any> | undefined>{   
    console.log(compiler)
    console.log(metadata)
    class DynamicComponent {
        @Output() buttonType: EventEmitter<string> = new EventEmitter<string>()

        // button click operation
        buttonPress() {
            this.buttonType.emit();
        }
    };
    const decoratedCmp = Component(metadata)(DynamicComponent);

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

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

@Component({
    selector: 'mvc-partial',
    template: `<div #dynamicHtml></div>`
})
//@Directive({ selector: 'mvc-partial' })
export class RenderingViewDynamic implements OnInit {
    @ViewChild('dynamicHtml', { read: ViewContainerRef }) target: ViewContainerRef;
    html: string = '<p></p>';
    @Input() url: string;
    cmpRef: ComponentRef<any>;

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

    ngOnInit() {
        this.http.get(this.url)
            .map(res => res.text())
            .subscribe(
            (html) => {
                this.html = 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.target.createComponent(factory!);
                    });
            },
            err => console.log(err),
            () => console.log('MvcPartial complete')
            );

    }

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

}

razor.component.html

&lt;mvc-partial [url]="'/View/Index'" (buttonType)="click()"&gt;&lt;/mvc-partial&gt;

razor.component.ts

click(){ console.log("In razor") }

我的问题是,按钮在我的动态 html 中,想要将它的事件绑定到 razor.ts 中。

like &lt;dynamic-html&gt;-&lt;mvc-partial&gt;-&lt;razor&gt; 怎么实现呢?

更新:尝试与服务通信

class DynamicComponent {
        constructor(private appService: AppService) { }

        buttonPress() {
            this.appService.onButtonClickAction.emit()
        }
    };
    const decoratedCmp = Component(metadata)(DynamicComponent);

    @NgModule({ imports: [CommonModule, RouterModule], declarations: [decoratedCmp], providers: [AppService] })

错误弹出:无法解析 DynamicComponent 的所有参数:(?)。

通过添加@Inject(forwardRef(() =&gt; AppService)解决上述错误

constructor( @Inject(forwardRef(() =>  AppService)) private appService: AppService) { } 

【问题讨论】:

  • 您不能将@Output()@Input() 与动态添加的组件一起使用。请参阅我在stackoverflow.com/questions/36325212/… 中的答案中第一个代码块中的注释掉的代码,以了解如何与动态添加的组件进行通信。也可以使用共享服务。
  • @GünterZöchbauer stackoverflow.com/questions/40725620/… 对我有什么帮助?
  • 为动态添加的 HTML 添加点击处理程序
  • 但我的问题是关于 DynamicComponent 有按钮我在 DynamicComponent 中处理它。 buttonPress() { this.buttonType.emit(); } 检查我的问题。 buttonType()razor.ts 中需要调用的那个。作为您的第一条评论,它可能也称为共享服务,但重复不合理。
  • 我明白了。我认为这是在标记为重复之后添加的。对不起,错了。

标签: angular typescript


【解决方案1】:

您可以使用 EventEmitter 将点击事件从您的孩子发送给您的父母:

clickEmitter = new EventEmitter();

clickEmitter.emit();

<your-child-component (clickEmitter)="functionInParent()"></your-child-component>

编辑: 如果您想根据您的评论访问您的子组件:&lt;dynamic-html&gt;-&lt;mvc-partial&gt;-&lt;razor&gt; 您可以使用主题标签 (#) 和主题标签名称或组件名称来引用组件

@ViewChild(MvcPartialComponent) mvcPartialComponent: MvcPartialComponent;

<mvc-partial #mvc-partial></mvc-partial>
@ViewChild('mvc-partial') mvcPartialComponent: MvcPartialComponent;

等等等等

【讨论】:

  • 在上述情况下无法做到这一点。因为流程是&lt;dynamic-html&gt;-&lt;mvc-partial&gt;-&lt;razor&gt; 按钮在dynamic-html 中,函数应该在razor 中调用
  • 然后你可以在组件上设置一个引用并直接调用该函数。查看我的更新答案
  • 是的。但问题是我的按钮在dynamic-html 中,我在各自的DynamicComponent 中处理它,所以MvcPartialComponent 的引用无法解决。 Parentrazor-Childmvc-partial-subChild(DynamicComponent)dynamic-html
  • 您可以创建一个命名并检查它是否已定义 。我真的不明白问题是什么。
  • 让我试试。如果你看到我的RenderingViewDynamic ,我会从mvc 得到Index.cshtml,其中包含&lt;button (click)="buttonPress"&gt; 分配给this.html 并创建一个DynamicComponent.ts 作为selector: 'dynamic-html' ,template: this.htmlDynamicComponentbuttonPress(){ console.log("In dynamic")}。现在在 buttonPress() 里面我需要和razor.ts进行通信
猜你喜欢
  • 2021-09-03
  • 2017-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-03
  • 1970-01-01
  • 2017-10-21
相关资源
最近更新 更多