繁体   English   中英

如何在 Angular 7 中从子组件到父属性指令进行通信?

[英]How to communicate from the child component to parent attribute directive in Angular 7?

我的目标是让自定义指令在其范围内侦听 DOM 事件; 并处理该事件。 在这种情况下,DOMEvent 将发生在我无法控制的第三方组件中。

在 Angular 中,我在组件中定义了以下模板。

该模板有一个指令(称为my-directive ),它与 ckeditor 组件的 keypress 事件挂钩。

我不拥有 ckeditor 的代码; 并且我试图避免不必更改任何代码,以便这可以成为一个可重用的钩子。

一些组件.ts

<!-- lots of irrelevant template code snipped -->
<my-directive>
  <ckeditor [editor]="Editor" (keypress)="pressed($event)"></ckeditor>
</my-directive>
<!-- lots of irrelevant template code snipped -->

my.directive.ts定义如下:

import { Directive, OnInit } from "@angular/core";

@Directive({
    selector: 'my-directive',
  })
  export class MyDirective implements OnInit {
    public pressed(e: Event) : void {
        console.table(e);
    }

    constructor(
    ) { }
    ngOnInit() : void {
    }
}

而 CKEditor 来自 angular-ckeditor 包; 使用以下导入:

import { CKEditorModule } from '@ckeditor/ckeditor5-angular'; import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';

当我尝试从 ckeditor 标签调用被pressed函数时; 它抱怨pressed不是一个功能:

exception-handler.ts:41 TypeError: _co.pressed is not a function
    at Object.eval [as handleEvent] (SomeComponent.html:60)
    at handleEvent (core.js:21673)
    at callWithDebugContext (core.js:22767)
    at Object.debugHandleEvent [as handleEvent] (core.js:22470)
    at dispatchEvent (core.js:19122)
    at core.js:19569
    at HTMLUnknownElement.<anonymous> (platform-browser.js:993)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
    at Object.onInvokeTask (core.js:16147)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422) "/myurl/1"

也许问题是 Angular 试图在ckeditor上调用ckeditor pressed()

所以我尝试使用模板引用变量:

<!-- lots of irrelevant template code snipped -->
<my-directive #md>
  <ckeditor [editor]="Editor" (keypress)="md.pressed($event)"></ckeditor>
</my-directive>
<!-- lots of irrelevant template code snipped -->

所以我得到了这个错误:

TypeError: jit_nodeValue_4(...).pressed is not a function
    at Object.eval [as handleEvent] (SomeComponent.html:60)
    at handleEvent (core.js:21673)
    at callWithDebugContext (core.js:22767)
    at Object.debugHandleEvent [as handleEvent] (core.js:22470)
    at dispatchEvent (core.js:19122)
    at core.js:19569
    at HTMLUnknownElement.<anonymous> (platform-browser.js:993)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
    at Object.onInvokeTask (core.js:16147)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422) "/myurl/1"

归根结底,我的问题是:

如何允许指令响应子组件中引发的标准 DOM 事件?

我不想修改子组件; 在某些情况下我不能(这不是我的代码)。 我希望可以将此指令添加到其他组件的模板中,并且不必在内部修改这些组件以允许此指令实现的新行为。

经过更多的调查; 似乎通过附加到子组件的模板声明来收听标准 DOM 事件是多余的,我可以通过执行以下操作来实现我想要的:

  1. @HostListener添加到MyDirective
import { Directive, OnInit } from "@angular/core";

@Directive({
    selector: 'my-directive',
  })
  export class MyDirective implements OnInit {
    public pressed(e: Event) : void {

    }
    @HostListener('keypress') onKeyPress(e: Event) {
        console.table(e);
    }
    constructor(
    ) { }
    ngOnInit() : void {
    }
}
  1. 修改模板以删除声明,并简单地将my-directive声明包裹在孩子周围:
<!-- lots of irrelevant template code snipped -->
<my-directive>
  <ckeditor [editor]="Editor"></ckeditor>
</my-directive>
<!-- lots of irrelevant template code snipped -->

现在,如果在my-directive标签内发生任何按键事件(无论是它还是它的子标签),它都会引发一个@HostListener将响应的事件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM