这是我打开弹出窗口的方法:
<div>
<a (click)="trigger = true">
<div>
<i class="pe-7s-file"></i>
</div>
</a>
<div popover clickOutside (clickOutside)="console.log('Outside')" *ngIf="trigger==true">
<p>Hello Popover</p>
</div>
</div>
当我单击第一个div时,它将在控制台中(外部)打印,我想在第一次打开弹出窗口而控制台上没有任何消息,而当我单击弹出式div外部时,控制台应该会打印。
这是我的主持人:
@Directive({
selector: '[clickOutside]'
})
export class ClickOutsideDirective {
constructor(private _elementRef: ElementRef) { }
@Output('clickOutside') clickOutside: EventEmitter<any> = new EventEmitter();
@HostListener('document:click', ['$event.target'])
onMouseEnter(targetElement) {
const clickedInside = this._elementRef.nativeElement.contains(targetElement);
if (!clickedInside) {
this.clickOutside.emit(null);
}
}
}
答案 0 :(得分:0)
我不确定您到目前为止想要达到的目标。因此,根据我的解释,我已将您的代码修改如下:
html
<div>
<a (click)="displayPopover()">
<div>
my content outside
</div>
</a>
<ng-container *ngIf="isDisplay">
<div clickOutside (clickOutside)="myHandler()" style="border: 1px solid black">
<p>Click me, nothing will happen</p>
</div>
</ng-container>
</div>
仅用于示例的组件ts:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
isDisplay: boolean = false;
myHandler() {
console.log('click outside');
this.isDisplay = false;
}
displayPopover() {
this.isDisplay = true;
}
}
指令:
@Directive({
selector: '[clickOutside]'
})
export class ClickOutsideDirective implements AfterViewInit, OnDestroy {
@Output('clickOutside') clickOutside: EventEmitter<void> = new EventEmitter();
squareMatrix: {
x1: number,
y1: number,
x2: number,
y2: number
};
sub: Subscription;
constructor(private _elementRef: ElementRef) { }
ngAfterViewInit() {
/**
* Populate current square x,y position.
*/
this.populateMatrix();
// Timeout is here to ignore first click. Not right way but do the job.
setTimeout(() => {
this.sub = fromEvent(window, 'click').subscribe((e: MouseEvent) => {
if(!this.checkIfClickOnSquare(e.clientX, e.clientY)) {
this.clickOutside.emit();
}
});
},100);
}
ngOnDestroy(){
if(this.sub) {
//Don't forget to unsubscribe.
this.sub.unsubscribe();
}
}
private populateMatrix() {
const {x, y, width, height} = this._elementRef.nativeElement.getBoundingClientRect();
this.squareMatrix = {
x1 : x,
y1: y,
x2: x + width,
y2: y + height
};
}
private checkIfClickOnSquare(currentX, currentY): boolean {
return (
currentX > this.squareMatrix.x1 &&
currentX < this.squareMatrix.x2 &&
currentY > this.squareMatrix.y1 &&
currentY < this.squareMatrix.y2
);
}
}
说明: 我创建了正方形矩阵,以具有实际绘制的Popover的点参考。基于这个正方形,在每次单击文档触发事件时,我检查当前x,y光标是否在当前DOMElement的内部或外部。
为防止首次单击,我在绑定事件之前已添加超时。做事的方法不正确。
如果愿意,可以查看live sample。