Angular2では、HostListenerデコレータ内の要素をどのようにターゲットにできますか?
@HostListener('dragstart', ['$event'])
onDragStart(ev:Event) {
console.log(ev);
}
@HostListener('document: dragstart', ['$event'])
onDragStart(ev:Event) {
console.log(ev);
}
@HostListener('myElement: dragstart', ['$event'])
onDragStart(ev:Event) {
console.log(ev);
}
@HostListener('myElement.myClass: dragstart', ['$event'])
onDragStart(ev:Event) {
console.log(ev);
}
最初の2つの作業。私が試した他のことは、EXCEPTION: Unsupported event target undefined for event dragstart
を発生させます
だから、ターゲット要素に実装できますか?どうやって?
@HostListener()
は、グローバルイベントターゲットとしてwindow
、document
、およびbody
のみをサポートします。それ以外の場合は、コンポーネントのHost要素のみをサポートします。
受け入れられた答えは実際に問題を解決するのに役立たないので、ここに解決策があります。
これを実現するためのより良い方法は、ディレクティブを作成することです。この方法では、任意の要素にディレクティブを追加でき、リスナーはこの特定の要素に対してのみトリガーします。
例えば:
@Directive({
selector: "[focus-out-directive]"
})
export class FocusOutDirective {
@Output() onFocusOut: EventEmitter<boolean> = new EventEmitter<false>();
@HostListener("focusout", ["$event"])
public onListenerTriggered(event: any): void {
this.onFocusOut.emit(true);
}
}
次に、このリスナーを適用するHTML要素にディレクティブセレクター(この場合はfocus-out-directive
)を追加し、コンポーネントでトリガーする関数を指定します。
例:
<input type='text' focus-out-directive (onFocusOut)='myFunction($event)'/>
グローバルリスナーのより良い方法は@hostliternerだと思いますが、いくつかの要素をターゲットにしたい場合はこのようにすることができます
<div (event)="onEvent($e)"></div>
angularコンポーネントで
onEvent($e) { //do something ... }
要素で聞く:
import { Renderer2 } from '@angular/core';
...
constructor(private renderer: Renderer2) {}
// Get this.myElement with document.getElement... or ElementRef
ngOnInit() {
// scroll or any other event
this.renderer.listen(this.myElement, 'scroll', (event) => {
// Do something with 'event'
console.log(this.myElement.scrollTop);
});
}
import { Directive, ElementRef, OnInit, Output, EventEmitter} from '@angular/core';
@Directive({
selector: '[checkClick]'
})
export class checkClickDirective implements OnInit {
@Output() public checkClick = new EventEmitter();
constructor(private _el: ElementRef) { }
@HostListener('click', ['$event.target']) public onClick(targetElement) {
const checkClick = this._el.nativeElement.contains(targetElement);
(checkClick)?this.checkClick.emit(true):this.checkClick.emit(false);
}
}
Googsが指摘したように、受け入れられた答えは質問に答えますが、解決策を見つける助けにはなりません。
さまざまな画面サイズの通知のリストを取得するために、すでに@HostListener
にあった機能を使用する方法が必要だったため、アレックスの答えに基づいて作成しました。
たとえば、私のアプリでは、通知ページはモバイルでは独自のルートを持っていますが、上記のタブレットや画面サイズのサイドバーに存在するため、@HostListener
は使用できません。サイドバーではなく、ページ全体の下部。
代わりに、<div>
を調べ、必要なものに興味を持って添付しました。したがって、次のコード:
attachListenerToContainer() {
let elementToListenTo = this.ele ? this.ele : 'window';
this.renderer.listen(elementToListenTo, 'scroll', (event) => {
if(!this.reachedBottom) {
if((getHeight(this.ele) + getScrollTop(this.ele)) >= getOffset(this.ele)) {
this.reachedBottom = true;
this.getNextNotificationsPage();
}
}
});
function getScrollTop(ele) {
return ele ? ele.scrollTop : window.scrollY;
}
function getHeight(ele) {
return ele ? ele.clientHeight : window.innerHeight;
}
function getOffset(ele) {
return ele ? ele.scrollHeight : document.body.offsetHeight;
}
}
this.ele
は、興味のあるコンテナdivで、タブレット用のngAfterViewInit()
ライフサイクルフックで検索します。その要素が見つからない場合は、代わりにウィンドウを使用します-@HostListener
を効果的にエミュレートします
また、ここで私が探していた方法、私の場合は、私が欲しかったコンテナ要素です:
this.ele = document.getElementsByClassName('notifications')[0];