仅在外部点击时调用函数无法按预期工作
only calling function on outside click not works as expected
在我的 angular 指令中,单击主机元素时会显示弹出窗口。当弹出窗口打开状态时,如果用户在任何地方点击外部,我需要关闭弹出窗口。为此,我尝试使用以下代码。但不起作用。 this.removeComponent();
方法总是调用。
@HostListener("window:mouseup", ["$event"]) clickedOut(event) {
if (event.target.nativeElement === this.hostElement) {
//when click on host element do nothing!
return;
}
//when click outside otherthan this.hostElement remove the componenet
this.removeComponent();
}
任何人都可以帮助我处理这种情况吗?
这应该可以解决您的问题,问题的发生是因为您正在将一个元素与一个元素数组进行比较,而元素数组始终为 false,从而给您带来错误。
@HostListener("window:mouseup", ["$event"]) clickedOut(event) {
if (this.hostElement.nativeElement.contains(event.target)) {
//when click on host element do nothing!
return;
}
else{
this.removeComponent();
}
//when click outside other than this.hostElement remove the component
}
应该是
@HostListener('window:mouseup', ['$event']) clickedOut(event) {
//you looking for "event.target" into "this.element.nativeElement"
if (!this.elementRef.nativeElement.contains(event.target)) {
console.log("outside")
}
else
{
console.log("inside")
}
}
注意:如果您不希望传播元素上的点击,请在 HostListener(点击)中使用 event.stopPropagation();
@HostListener('click', ['$event']) onClick(event) {
....
event.stopPropagation(); //<---this line
}
或者完全删除它,只使用大约 window:mouseup
的 hostListener
stackblitz(仅在控制台点击外侧和点击内侧显示)
更新 使用此方法,您会得到如此多的“点击外部”元素以及您拥有的指令
如果我们的目标是显示弹出窗口或类似窗口,那也没有问题,因为通常我们当时没有太多元素。但是想象一下我们的指令只是放置一个边框——例如——。我们应该采取另一种方法。首先我们可以使用 HostBinding,所以我们的指令只能管理创建一个边框。看到我们将 elementRef 注入为“public”
@Directive({
selector: '[showpop]'
})
export class ShowPopDirective {
border: boolean=false;
constructor( public elementRef: ElementRef ) {}
@HostBinding('style.border') get _(){return this.border?'1px solid red':null}
}
而且我们可以从外部组件控制外部
@ViewChildren(ShowPopDirective) items:QueryList<ShowPopDirective>
@HostListener('window:mouseup', ['$event']) clickedOut(event) {
this.items.forEach(x=>{
x.border=!x.border && x.elementRef.nativeElement.contains(event.target)
})
}
在我的 angular 指令中,单击主机元素时会显示弹出窗口。当弹出窗口打开状态时,如果用户在任何地方点击外部,我需要关闭弹出窗口。为此,我尝试使用以下代码。但不起作用。 this.removeComponent();
方法总是调用。
@HostListener("window:mouseup", ["$event"]) clickedOut(event) {
if (event.target.nativeElement === this.hostElement) {
//when click on host element do nothing!
return;
}
//when click outside otherthan this.hostElement remove the componenet
this.removeComponent();
}
任何人都可以帮助我处理这种情况吗?
这应该可以解决您的问题,问题的发生是因为您正在将一个元素与一个元素数组进行比较,而元素数组始终为 false,从而给您带来错误。
@HostListener("window:mouseup", ["$event"]) clickedOut(event) {
if (this.hostElement.nativeElement.contains(event.target)) {
//when click on host element do nothing!
return;
}
else{
this.removeComponent();
}
//when click outside other than this.hostElement remove the component
}
应该是
@HostListener('window:mouseup', ['$event']) clickedOut(event) {
//you looking for "event.target" into "this.element.nativeElement"
if (!this.elementRef.nativeElement.contains(event.target)) {
console.log("outside")
}
else
{
console.log("inside")
}
}
注意:如果您不希望传播元素上的点击,请在 HostListener(点击)中使用 event.stopPropagation();
@HostListener('click', ['$event']) onClick(event) {
....
event.stopPropagation(); //<---this line
}
或者完全删除它,只使用大约 window:mouseup
的 hostListenerstackblitz(仅在控制台点击外侧和点击内侧显示)
更新 使用此方法,您会得到如此多的“点击外部”元素以及您拥有的指令
如果我们的目标是显示弹出窗口或类似窗口,那也没有问题,因为通常我们当时没有太多元素。但是想象一下我们的指令只是放置一个边框——例如——。我们应该采取另一种方法。首先我们可以使用 HostBinding,所以我们的指令只能管理创建一个边框。看到我们将 elementRef 注入为“public”
@Directive({
selector: '[showpop]'
})
export class ShowPopDirective {
border: boolean=false;
constructor( public elementRef: ElementRef ) {}
@HostBinding('style.border') get _(){return this.border?'1px solid red':null}
}
而且我们可以从外部组件控制外部
@ViewChildren(ShowPopDirective) items:QueryList<ShowPopDirective>
@HostListener('window:mouseup', ['$event']) clickedOut(event) {
this.items.forEach(x=>{
x.border=!x.border && x.elementRef.nativeElement.contains(event.target)
})
}