当用户单击下拉列表之外的任何位置时,我想关闭我的登录菜单下拉列表,我想使用Angular2和Angular2“方法”来做到这一点……
我实现了一个解决方案,但我真的对它没有信心。我认为一定有一个最简单的方法可以达到同样的结果,所以如果你有任何想法…让我们讨论:)!
这是我的实现:
这是我的下拉列表的组件:
这是密码
export class UserMenuComponent {
_isVisible: boolean = false;
_subscriptions: Subscription<any> = null;
constructor(public subjects: SubjectsService) {
}
onClick(event) {
event.stopPropagation();
}
set isVisible(v) {
if( v ){
setTimeout( () => {
this._subscriptions = this.subjects.userMenu.subscribe((e) => {
this.isVisible = false;
})
}, 0);
} else {
this._subscriptions.unsubscribe();
}
this._isVisible = v;
}
get isVisible() {
return this._isVisible;
}
}
另一方面,还有应用程序组件(它是下拉组件的父组件):
这是代码:
export class AppComponent {
constructor( public subjects: SubjectsService) {
document.addEventListener('click', () => this.onClick());
}
onClick( ) {
this.subjects.userMenu.next({});
}
}
这个设置超时将订阅延迟到当前JavaScript代码结束,这解决了问题,但在我看来是一种非常优雅的方式。
如果您知道更清洁,更好,更智能,更快或更强的解决方案,请告诉我:)!
您可以使用(文档:点击)
事件:
@Component({
host: {
'(document:click)': 'onClick($event)',
},
})
class SomeComponent() {
constructor(private _eref: ElementRef) { }
onClick(event) {
if (!this._eref.nativeElement.contains(event.target)) // or some similar check
doSomething();
}
}
另一种方法是创建自定义事件作为指令。查看Ben Nadel的这些帖子:
我发现这个clickOut
指令:https://github.com/chliebel/angular2-click-outside.我检查它,它工作得很好(我只复制clickOutside.指令. ts
到我的项目)。你可以这样使用它:
<div (clickOutside)="close($event)"></div>
其中close
是您的函数,当用户单击div外部时将调用它。这是处理问题中描述的问题的非常优雅的方法。
如果您使用上述指令关闭弹出窗口,请记住首先添加event. stop Proploation()
以按钮单击打开弹出窗口的事件处理程序。
下面我从文件复制原始指令代码clickOutside. Directive.ts
(如果链接将来会停止工作)-作者是Christian Liebel:
import {Directive, ElementRef, Output, EventEmitter, HostListener} from '@angular/core';
@Directive({
selector: '[clickOutside]'
})
export class ClickOutsideDirective {
constructor(private _elementRef: ElementRef) {
}
@Output()
public clickOutside = new EventEmitter<MouseEvent>();
@HostListener('document:click', ['$event', '$event.target'])
public onClick(event: MouseEvent, targetElement: HTMLElement): void {
if (!targetElement) {
return;
}
const clickedInside = this._elementRef.nativeElement.contains(targetElement);
if (!clickedInside) {
this.clickOutside.emit(event);
}
}
}
我已经这样做了。
在文档上添加了一个事件侦听器,单击
并在该处理程序中检查我的容器
是否包含event.target
,如果没有-隐藏下拉列表。
它看起来像这样。
@Component({})
class SomeComponent {
@ViewChild('container') container;
@ViewChild('dropdown') dropdown;
constructor() {
document.addEventListener('click', this.offClickHandler.bind(this)); // bind on doc
}
offClickHandler(event:any) {
if (!this.container.nativeElement.contains(event.target)) { // check click origin
this.dropdown.nativeElement.style.display = "none";
}
}
}