[英]Angular2, HostListener, how can I target an element? can I target based on class?
In Angular2, how can I target an element within the HostListener decorator?在 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);
}
The two first work.两人第一次工作。 Any other thing I've tried raises an EXCEPTION: Unsupported event target undefined for event dragstart
我尝试过的任何其他事情都会引发EXCEPTION: Unsupported event target undefined for event dragstart
So, can I implement it to a targeted element?那么,我可以将它实现到目标元素吗? How?如何?
@HostListener()
仅支持window
、 document
和body
作为全局事件目标,否则仅支持组件宿主元素。
Since the accepted answer doesn't actually help to solve the problem, here is a solution.由于接受的答案实际上并不能帮助解决问题,因此这里有一个解决方案。
A better way to achieve this is by creating a directive, this way you can add the directive to any element you wish, and the listeners will only trigger for this particular element.实现此目的的更好方法是创建指令,这样您可以将指令添加到您希望的任何元素,并且侦听器只会触发此特定元素。
For example:例如:
@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);
}
}
Then on your HTML elements you wish to apply this listener to, just add the directive selector, in this case focus-out-directive
, and then supply the function you wish to trigger on your component.然后在您希望应用此侦听器的 HTML 元素上,只需添加指令选择器,在本例中focus-out-directive
,然后提供您希望在组件上触发的功能。
Example:例子:
<input type='text' focus-out-directive (onFocusOut)='myFunction($event)'/>
I think better way for global listener is @hostliterner but if you want to target some element you can do like this我认为全局监听器的更好方法是@hostliterner,但如果你想定位某些元素,你可以这样做
<div (event)="onEvent($e)"></div>
in your angular component在你的角度分量中
onEvent($e) { //do something ... }
Listen on an element:听一个元素:
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);
}
}
in component template在组件模板中
<div (event)="onMouseEnter()">
<p>United States of America (mouseenter)</p>
</div>
<div (event)="onMouseOut()">
<p>United States of America (mouseout)</p>
</div>
in class component在类组件中
import { Component, OnInit, HostListener } from '@angular/core';
@Component({
selector: 'app-simpleevent',
templateUrl: './simpleevent.component.html',
styleUrls: ['./simpleevent.component.css']
})
export class SimpleeventComponent implements OnInit {
@HostListener("mouseenter", ["$event"]) onMouseEnter(event: Event) {
console.log(event.type);
}
@HostListener("mouseout", ["$event"]) onMouseOut(event: Event) {
console.log(event.type);
console.log(event.target)
}
constructor() { }
ngOnInit() {
}
}
As pointed out by Googs, the accepted answer does answer the question but doesn't help find a solution.正如 Googs 所指出的,接受的答案确实回答了问题,但无助于找到解决方案。
I built upon alex's answer as I needed a way to use the functionality I already had in my @HostListener
for retrieving a list of notifications for different screen sizes.我建立在 alex 的答案之上,因为我需要一种方法来使用我在@HostListener
中已有的功能来检索不同屏幕尺寸的通知列表。
For example, in my app - the notifications page has its own route on mobile but existed in the sidebar on tablet and screen sizes above, so I couldn't use the @HostListener
there as it would only trigger when I hit the bottom of the whole page and not the sidebar.例如,在我的应用程序中 - 通知页面在移动设备上有自己的路线,但存在于平板电脑的侧边栏中和上面的屏幕尺寸,所以我不能在那里使用@HostListener
因为它只会在我点击底部时触发整个页面而不是侧边栏。
Instead I looked up the <div>
I was interested in and attached what I needed.相反,我查找了我感兴趣的<div>
并附上了我需要的内容。 So the following code:所以下面的代码:
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;
}
}
The this.ele
is the container div I'm interested in which I look up in the ngAfterViewInit()
lifecycle hook for tablet and above. this.ele
是我感兴趣的容器 div,我在平板电脑及更高版本的ngAfterViewInit()
生命周期挂钩中查找它。 If I can't find that element then I use the window instead - effectively emulating the @HostListener
如果我找不到那个元素,那么我会使用窗口来代替 - 有效地模拟@HostListener
Also - here's how I was looking up, in my case, the container element I wanted:另外 - 这是我查找的方式,在我的情况下,我想要的容器元素:
this.ele = document.getElementsByClassName('notifications')[0];
If button
is clicked up to level
deep in directive, then toggle class: hide
如果button
被点击到指令level
深处,则切换类: hide
import { Directive, HostBinding, HostListener } from '@angular/core'
@Directive({
selector: '[Toggle]',
})
export class ToggleDirective {
@HostBinding('class.hide') isClosed = true
@HostListener('click', ['$event.target']) toggleDropdown(el: HTMLElement) {
if (this.isButton(el)) this.isClosed = !this.isClosed
}
isButton(el: HTMLElement, level = 3) {
for (let btn: HTMLElement | undefined | null = el; level > 0; level--) {
if (btn?.tagName === 'BUTTON') return true
btn = btn?.parentElement
}
return false
}
constructor() {}
}
Try this (listening on tab key)试试这个(听 Tab 键)
@HostListener('document:keydown.tab', ['$event']) onKeydownHandler(event: KeyboardEvent) {
if ((document as any).getElementById('parentIdOfHtml').contains((event as any).target)) {
debugger
}
}
You can also target any element without @hostlistener and can add necessary events by the following way您还可以在没有@hostlistener 的情况下定位任何元素,并且可以通过以下方式添加必要的事件
import { AfterViewInit, Component, ElementRef} from '@angular/core';
constructor(private elementRef:ElementRef) {}
ngAfterViewInit() {
this.elementRef.nativeElement.querySelector('my-element')
.addEventListener('click', this.onClick.bind(this));
}
onClick(event) {
console.log(event);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.