由于没有模板,在指令中监听子元素事件的最佳方法是什么?有没有可能与HostListener
?如果没有,还有其他方法吗?
还有这个类似的问题:How to listen for child event from parent directive in Angular2,但建议的方法并没有解决我的问题,因为我的指令和子元素不在同一个模板中(指令在主机上)。
干杯!
编辑#1
这就是我目前正在做的事情(必须有更好的方法):
首先将ElementRef
注入我的指令:
constructor(private elView: ElementRef) {}
然后用jQuery(或普通的JS)绑定:
$(this.elView.nativeElement)
.on('drag', '#childId', this.slide.bind(this))
如果您要收听的事件是一个冒泡的本机DOM事件,那么您可以使用@HostListener()
@HostListener('click', ['$event'])
handleClick(event) {
// handle event
}
如果它们是子组件的输出,您可以查询它们并订阅它们的输出
@ContentChildren(ChildComponent) children:QueryList<ChildComponent>;
ngAfterContentInit() {
this.children.toArray().forEach((item) => {
item.someOutput.subscribe(...);
});
}
或者您可以使用您在问题中链接的答案中使用的方法。
您可以考虑通过服务类使组件相互通信。
// service class
class Service {
private someEventSource = new Subject();
public someEvent = this.someEventSource.asObservable();
public invokeAnEvent (data: string) {
this.someEventSource.next(data);
}
}
// parentComponent class
Service.someEvent.subscribe(data => {
console.log(data);
});
// childComponent class
Service.invokeAnEvent('some data to pass');
来自Angular文档: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service
我对这个问题的解决方案是在根组件中添加ngAfterContentChecked
并在那里选择我所有的相关元素并添加事件。例:
ngAfterContentChecked() {
//console.log('MASTER ngAfterContentChecked')
let rgx = /^[0-9,\.]+$/;
let preventNonNumber = e => {
//let v = (e.target as HTMLInputElement).value
if (
// Allow: Delete, Backspace, Tab, Escape, Enter
[46, 8, 9, 27, 13].indexOf(e.keyCode) !== -1 ||
(e.keyCode === 65 && e.ctrlKey === true) || // Allow: Ctrl+A
(e.keyCode === 67 && e.ctrlKey === true) || // Allow: Ctrl+C
(e.keyCode === 86 && e.ctrlKey === true) || // Allow: Ctrl+V
(e.keyCode === 88 && e.ctrlKey === true) || // Allow: Ctrl+X
(e.keyCode === 65 && e.metaKey === true) || // Cmd+A (Mac)
(e.keyCode === 67 && e.metaKey === true) || // Cmd+C (Mac)
(e.keyCode === 86 && e.metaKey === true) || // Cmd+V (Mac)
(e.keyCode === 88 && e.metaKey === true) || // Cmd+X (Mac)
(e.keyCode >= 35 && e.keyCode <= 39) // Home, End, Left, Right
) {
return; // let it happen, don't do anything
}
if (rgx.test(e['key']) == false) {
e.preventDefault();
}
};
let inputs = document.querySelectorAll('label-input[numberOnly] input, cbx-label-input[numberOnly] input')
//console.log(inputs)
inputs.forEach(i => (i as HTMLInputElement).onkeydown = preventNonNumber)
}
注意每次触摸输入时都会触发ngAfterContentChecked,因此选择器每次都会运行,并且还会设置该函数,但由于它是一个静态函数,您只需覆盖它就不会出现太多的性能问题。