我的目标是让自定义指令在其作用域内侦听DOM事件;并处理该事件。在这种情况下,该DOMEvent将发生在我无法控制的第三方组件中。
在Angular中,我在组件中定义了以下模板。
此模板的指令(称为my-directive
)已与ckeditor组件的keypress事件挂钩。
我不拥有ckeditor的代码;并且试图摆脱不必更改任何代码的麻烦,以便使它成为可重用的钩子。
<!-- 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正在尝试在pressed()
上调用ckeditor
?
所以我尝试使用模板引用变量:
<!-- 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事件?
我不想修改子组件;在某些情况下,我做不到(这不是我的代码)。我希望可以将该指令添加到其他组件的模板中,而不必在内部进行修改以允许该指令实现新的行为。
答案 0 :(得分:0)
经过更多调查;似乎通过附加到子组件的模板声明来侦听标准DOM事件是过大的,并且我可以通过执行以下操作来实现所需的目标:
@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 {
}
}
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
将对此做出响应。