Skip to content

Commit a02011f

Browse files
fix(OpenUI5Support): fix sap.m.Select inside a ui5-dialog (#11939)
* fix(OpenUI5Support): fix sap.m.Select inside a ui5-dialog
1 parent 8bcf85f commit a02011f

File tree

4 files changed

+88
-6
lines changed

4 files changed

+88
-6
lines changed

packages/base/src/features/OpenUI5Support.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import patchPatcher from "./patchPatcher.js";
22
import type { OpenUI5Patcher } from "./patchPatcher.js";
3-
import patchPopup from "./patchPopup.js";
3+
import {
4+
patchPopup,
5+
addOpenedPopup,
6+
removeOpenedPopup,
7+
getTopmostPopup,
8+
} from "./patchPopup.js";
49
import type { OpenUI5Popup } from "./patchPopup.js";
510
import { registerFeature } from "../FeaturesRegistry.js";
611
import { setTheme } from "../config/Theme.js";
@@ -223,6 +228,18 @@ class OpenUI5Support {
223228

224229
return !!link.href.match(/\/css(-|_)variables\.css/);
225230
}
231+
232+
static addOpenedPopup(popup: object) {
233+
addOpenedPopup(popup);
234+
}
235+
236+
static removeOpenedPopup(popup: object) {
237+
removeOpenedPopup(popup);
238+
}
239+
240+
static getTopmostPopup() {
241+
return getTopmostPopup();
242+
}
226243
}
227244

228245
registerFeature("OpenUI5Support", OpenUI5Support);

packages/base/src/features/patchPopup.ts

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// OpenUI5's Control.js subset
2+
import getSharedResource from "../getSharedResource.js";
3+
24
type Control = {
35
getDomRef: () => HTMLElement | null,
46
}
@@ -14,6 +16,24 @@ type OpenUI5Popup = {
1416
}
1517
};
1618

19+
// contains all OpenUI5 and Web Component popups that are currently opened
20+
const AllOpenedPopupsRegistry = getSharedResource<{ openedRegistry: Array<object> }>("AllOpenedPopupsRegistry", { openedRegistry: [] });
21+
22+
const addOpenedPopup = (popup: object) => {
23+
AllOpenedPopupsRegistry.openedRegistry.push(popup);
24+
};
25+
26+
const removeOpenedPopup = (popup: object) => {
27+
const index = AllOpenedPopupsRegistry.openedRegistry.indexOf(popup);
28+
if (index > -1) {
29+
AllOpenedPopupsRegistry.openedRegistry.splice(index, 1);
30+
}
31+
};
32+
33+
const getTopmostPopup = () => {
34+
return AllOpenedPopupsRegistry.openedRegistry[AllOpenedPopupsRegistry.openedRegistry.length - 1];
35+
};
36+
1737
const openNativePopover = (domRef: HTMLElement) => {
1838
domRef.setAttribute("popover", "manual");
1939
domRef.showPopover();
@@ -52,6 +72,8 @@ const patchOpen = (Popup: OpenUI5Popup) => {
5272
}
5373
}
5474
}
75+
76+
addOpenedPopup(this);
5577
};
5678
};
5779

@@ -64,15 +86,17 @@ const patchClosed = (Popup: OpenUI5Popup) => {
6486
if (domRef) {
6587
closeNativePopover(domRef); // unset the popover attribute and close the native popover, but only if still in DOM
6688
}
89+
90+
removeOpenedPopup(this);
6791
};
6892
};
6993

7094
const patchFocusEvent = (Popup: OpenUI5Popup) => {
7195
const origFocusEvent = Popup.prototype.onFocusEvent;
7296
Popup.prototype.onFocusEvent = function onFocusEvent(e: FocusEvent) {
73-
const isTypeFocus = e.type === "focus" || e.type === "activate";
74-
const target = e.target as HTMLElement;
75-
if (!isTypeFocus || !target.closest("[ui5-popover],[ui5-responsive-popover],[ui5-dialog]")) {
97+
// If the popup is the topmost one, we call the original focus event handler from the OpenUI5 Popup,
98+
// otherwise the focus event is handled by the Web Component Popup.
99+
if (this === getTopmostPopup()) {
76100
origFocusEvent.call(this, e);
77101
}
78102
};
@@ -91,5 +115,11 @@ const patchPopup = (Popup: OpenUI5Popup) => {
91115
patchFocusEvent(Popup);// Popup.prototype.onFocusEvent
92116
};
93117

94-
export default patchPopup;
118+
export {
119+
patchPopup,
120+
addOpenedPopup,
121+
removeOpenedPopup,
122+
getTopmostPopup,
123+
};
124+
95125
export type { OpenUI5Popup };

packages/main/src/popup-utils/OpenedPopupsRegistry.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import getSharedResource from "@ui5/webcomponents-base/dist/getSharedResource.js";
22
import { isEscape } from "@ui5/webcomponents-base/dist/Keys.js";
3+
import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js";
4+
import type OpenUI5Support from "@ui5/webcomponents-base/dist/features/OpenUI5Support.js";
35
import type Popup from "../Popup.js";
46

57
type RegisteredPopup = {
@@ -8,13 +10,24 @@ type RegisteredPopup = {
810
}
911

1012
const OpenedPopupsRegistry = getSharedResource<{ openedRegistry: Array<RegisteredPopup> }>("OpenedPopupsRegistry", { openedRegistry: [] });
13+
const openUI5Support = getFeature<typeof OpenUI5Support>("OpenUI5Support");
14+
15+
function registerPopupWithOpenUI5Support(popup: object) {
16+
openUI5Support?.addOpenedPopup(popup);
17+
}
18+
19+
function unregisterPopupWithOpenUI5Support(popup: object) {
20+
openUI5Support?.removeOpenedPopup(popup);
21+
}
1122

1223
const addOpenedPopup = (instance: Popup, parentPopovers: Array<Popup> = []) => {
1324
if (!OpenedPopupsRegistry.openedRegistry.some(popup => popup.instance === instance)) {
1425
OpenedPopupsRegistry.openedRegistry.push({
1526
instance,
1627
parentPopovers,
1728
});
29+
30+
registerPopupWithOpenUI5Support(instance);
1831
}
1932

2033
_updateTopModalPopup();
@@ -29,6 +42,8 @@ const removeOpenedPopup = (instance: Popup) => {
2942
return el.instance !== instance;
3043
});
3144

45+
unregisterPopupWithOpenUI5Support(instance);
46+
3247
_updateTopModalPopup();
3348

3449
if (!OpenedPopupsRegistry.openedRegistry.length) {
@@ -46,8 +61,14 @@ const _keydownListener = (event: KeyboardEvent) => {
4661
}
4762

4863
if (isEscape(event)) {
64+
const topmostPopup = OpenedPopupsRegistry.openedRegistry[OpenedPopupsRegistry.openedRegistry.length - 1].instance;
65+
66+
if (openUI5Support && topmostPopup !== openUI5Support.getTopmostPopup()) {
67+
return;
68+
}
69+
4970
event.stopPropagation();
50-
OpenedPopupsRegistry.openedRegistry[OpenedPopupsRegistry.openedRegistry.length - 1].instance.closePopup(true);
71+
topmostPopup.closePopup(true);
5172
}
5273
};
5374

packages/main/test/pages/DialogAndOpenUI5Dialog.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,19 @@
5252
document.getElementById("dialog1").open = true;
5353
});
5454

55+
sap.ui.require(["sap/m/Select", "sap/ui/core/Item"], (Select, Item) => {
56+
new Select({
57+
items: [
58+
new Item({ text: "Item 1" }),
59+
new Item({ text: "Item 2" }),
60+
new Item({ text: "Item 3" })
61+
],
62+
change: function (oEvent) {
63+
console.error("Selected item:", oEvent.getParameter("selectedItem").getText());
64+
}
65+
}).placeAt("dilog1content");
66+
});
67+
5568
document.getElementById("dialogButton").addEventListener("click", function () {
5669
sap.ui.require(["sap/m/Button", "sap/m/Dialog"], (Button, Dialog) => {
5770
new Dialog({
@@ -81,6 +94,7 @@
8194
<ui5-button id="myButton">Open WebC Dialog</ui5-button>
8295
</div>
8396
<ui5-dialog id="dialog1" header-text="This is an WebC Dialog 1">
97+
<div id="dilog1content"></div>
8498
<ui5-button id="dialogButton">Open UI5 dialog</ui5-button>
8599
</ui5-dialog>
86100
<ui5-dialog id="newDialog1" header-text="This is an WebC Dialog 2">

0 commit comments

Comments
 (0)