From 5f65ffd4325fa0d6d4973c397079fe7df6f1dce7 Mon Sep 17 00:00:00 2001 From: "olivier.T" Date: Mon, 4 May 2026 17:32:50 +0200 Subject: [PATCH] ES-31345 fix(click-outside): guard against detached DOM nodes when datepicker closes ngx-bootstrap removes from the DOM synchronously on date selection, before the click event finishes bubbling. This caused sqClickOutside to emit a false outside-click, collapsing the parent panel. - click-outside.ts: bail out early when event.target is no longer in document.body - dropdown.service.ts: same guard in BsDropdownService.clearMenus for [data-bs-toggle="dropdown"] contexts Co-Authored-By: Claude Sonnet 4.6 --- projects/components/action/bootstrap/dropdown.service.ts | 6 ++++++ projects/components/utils/directives/click-outside.ts | 3 +++ 2 files changed, 9 insertions(+) diff --git a/projects/components/action/bootstrap/dropdown.service.ts b/projects/components/action/bootstrap/dropdown.service.ts index ede110b3b..1473460dc 100644 --- a/projects/components/action/bootstrap/dropdown.service.ts +++ b/projects/components/action/bootstrap/dropdown.service.ts @@ -231,6 +231,12 @@ export class BsDropdownService implements OnDestroy { event.type === 'keyup' && event.key !== Keys.tab)) { return; } + if (event?.type === 'click') { + const target = event.target as HTMLElement; + if (!this.document.body.contains(target) || target.closest('bs-datepicker-container, bs-daterangepicker-container')) { + return; + } + } this._events.next({type: "clear", sourceEvent: event}); } diff --git a/projects/components/utils/directives/click-outside.ts b/projects/components/utils/directives/click-outside.ts index f3b5bbfc8..a99eaf564 100644 --- a/projects/components/utils/directives/click-outside.ts +++ b/projects/components/utils/directives/click-outside.ts @@ -32,6 +32,9 @@ export class ClickOutside { if (this.element.offsetWidth === 0) { return; } + if (!document.body.contains(event.target)) { + return; + } if (event.target === document.body && document.elementFromPoint(event.pageX, event.pageY) !== event.target) { return; }