From b868d9e12889eb50d39cb59078038df400b8f720 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Tue, 14 May 2024 18:16:08 +0200 Subject: [PATCH] fix(cdk/overlay): skip trigger interactions in outside click event Adds some logic to skip the trigger when considering clicks outside of the overlay since filtering them is the most common case (e.g. we do it in some of our components) and can be annoying to deal with. Fixes #28949. --- src/cdk/overlay/overlay-directives.ts | 32 ++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/cdk/overlay/overlay-directives.ts b/src/cdk/overlay/overlay-directives.ts index 4775bfe6f7c3..87315cbf6c03 100644 --- a/src/cdk/overlay/overlay-directives.ts +++ b/src/cdk/overlay/overlay-directives.ts @@ -27,6 +27,7 @@ import { booleanAttribute, inject, } from '@angular/core'; +import {_getEventTarget} from '@angular/cdk/platform'; import {Subscription} from 'rxjs'; import {takeWhile} from 'rxjs/operators'; import {Overlay} from './overlay'; @@ -311,7 +312,12 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges { }); this._overlayRef.outsidePointerEvents().subscribe((event: MouseEvent) => { - this.overlayOutsideClick.next(event); + const origin = this._getOriginElement(); + const target = _getEventTarget(event) as Element | null; + + if (!origin || (origin !== target && !origin.contains(target))) { + this.overlayOutsideClick.next(event); + } }); } @@ -367,7 +373,7 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges { })); return positionStrategy - .setOrigin(this._getFlexibleConnectedPositionStrategyOrigin()) + .setOrigin(this._getOrigin()) .withPositions(positions) .withFlexibleDimensions(this.flexibleDimensions) .withPush(this.push) @@ -379,14 +385,12 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges { /** Returns the position strategy of the overlay to be set on the overlay config */ private _createPositionStrategy(): FlexibleConnectedPositionStrategy { - const strategy = this._overlay - .position() - .flexibleConnectedTo(this._getFlexibleConnectedPositionStrategyOrigin()); + const strategy = this._overlay.position().flexibleConnectedTo(this._getOrigin()); this._updatePositionStrategy(strategy); return strategy; } - private _getFlexibleConnectedPositionStrategyOrigin(): FlexibleConnectedPositionStrategyOrigin { + private _getOrigin(): FlexibleConnectedPositionStrategyOrigin { if (this.origin instanceof CdkOverlayOrigin) { return this.origin.elementRef; } else { @@ -394,6 +398,22 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges { } } + private _getOriginElement(): Element | null { + if (this.origin instanceof CdkOverlayOrigin) { + return this.origin.elementRef.nativeElement; + } + + if (this.origin instanceof ElementRef) { + return this.origin.nativeElement; + } + + if (typeof Element !== 'undefined' && this.origin instanceof Element) { + return this.origin; + } + + return null; + } + /** Attaches the overlay and subscribes to backdrop clicks if backdrop exists */ private _attachOverlay() { if (!this._overlayRef) {