diff --git a/packages/base/hash.txt b/packages/base/hash.txt index 7f53e8456d7a..8baf163389a6 100644 --- a/packages/base/hash.txt +++ b/packages/base/hash.txt @@ -1 +1 @@ -ydKuAqEtZBlQWCoH/ufRUwgv+qU= \ No newline at end of file +XgquM3ggzotOfecoo9jjwDTSvdQ= diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index fcf94497abd9..a5be902aad80 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -366,6 +366,14 @@ const metadata = { type: Boolean, }, + openOnMobile: { + type: Boolean, + }, + + open: { + type: Boolean, + }, + /** * Indicates whether the visual focus is on the value state header * @private @@ -374,10 +382,6 @@ const metadata = { type: Boolean, }, - open: { - type: Boolean, - }, - _input: { type: Object, }, @@ -586,6 +590,9 @@ class Input extends UI5Element { // Indicates, if the user pressed the BACKSPACE key. this._backspaceKeyDown = false; + // Indicates, if the user is typing. Gets reset once popup is closed + this.isTyping = false; + // all sementic events this.EVENT_CHANGE = "change"; this.EVENT_INPUT = "input"; @@ -616,9 +623,17 @@ class Input extends UI5Element { } this.effectiveShowClearIcon = (this.showClearIcon && !!this.value && !this.readonly && !this.disabled); - this.open = this.open && (!!this.suggestionItems.length || this._isPhone); const FormSupport = getFeature("FormSupport"); + const hasItems = this.suggestionItems.length; + const hasValue = !!this.value; + const isFocused = this === document.activeElement; + + if (this._isPhone) { + this.open = this.openOnMobile; + } else { + this.open = hasValue && hasItems && isFocused && this.isTyping; + } if (FormSupport) { FormSupport.syncNativeHiddenInput(this); @@ -794,8 +809,6 @@ class Input extends UI5Element { this._isValueStateFocused = false; this.focused = true; } - - this.open = false; } async _onfocusin(event) { @@ -827,13 +840,13 @@ class Input extends UI5Element { return; } - this.closePopover(); + this.open = false; this._clearPopoverFocusAndSelection(); this.previousValue = ""; this.lastConfirmedValue = ""; this.focused = false; // invalidating property - this.open = false; + this.isTyping = false; } _clearPopoverFocusAndSelection() { @@ -851,7 +864,7 @@ class Input extends UI5Element { _click(event) { if (isPhone() && !this.readonly && this.Suggestions) { this.blur(); - this.open = true; + this.openOnMobile = true; } } @@ -956,11 +969,9 @@ class Input extends UI5Element { if (this.Suggestions) { this.Suggestions.updateSelectedItemPosition(null); - - if (!this._isPhone) { - this.open = !!inputDomRef.value; - } } + + this.isTyping = true; } _handleResize() { @@ -986,6 +997,10 @@ class Input extends UI5Element { this.blur(); this.focused = false; } + + this.isTyping = false; + this.openOnMobile = false; + this.open = false; } /** @@ -1053,6 +1068,9 @@ class Input extends UI5Element { this.suggestionSelectionCanceled = false; this.fireEvent(this.EVENT_SUGGESTION_ITEM_SELECT, { item }); + + this.isTyping = false; + this.openOnMobile = false; } previewSuggestion(item) { diff --git a/packages/main/test/pages/InputsLazyLoading.html b/packages/main/test/pages/InputsLazyLoading.html new file mode 100644 index 000000000000..80e34ec85b5c --- /dev/null +++ b/packages/main/test/pages/InputsLazyLoading.html @@ -0,0 +1,207 @@ + + + + + + + + Input Lazy Loading + + + + + + + + + + +
+

Lazy loading items oninput

+ + +
+ +
+

Lazy load items on first type in

+ + +
+ +
+

Preload items

+ + +
+ +
+

Hardcoded items

+ + + Dryanovo + Gabrovo + Sofia + Yablanitsa + New York + +
+ +
+ +
+

Lazy loading items oninput

+ + +
+ +
+

Lazy load items on first type in

+ + +
+ +
+

Preload items

+ + +
+ +
+

Hardcoded items

+ + + + + + + + +
+ + + + + + \ No newline at end of file diff --git a/packages/main/test/specs/Input.spec.js b/packages/main/test/specs/Input.spec.js index de6ca26cee85..8e854a9f70f5 100644 --- a/packages/main/test/specs/Input.spec.js +++ b/packages/main/test/specs/Input.spec.js @@ -1118,3 +1118,45 @@ describe("XSS tests for suggestions", () => { })); }); }); + + +describe("Lazy loading", () => { + beforeEach(async () => { + await browser.url(`http://localhost:${PORT}/test-resources/pages/InputsLazyLoading.html`); + }); + + it("Lazy loading opens the picker once items are populated", async () => { + const input = await $("#field"); + const inner = await input.shadow$("input"); + const staticAreaClassName = await browser.getStaticAreaItemClassName("#field"); + const respPopover = await $(`.${staticAreaClassName}`).shadow$("ui5-responsive-popover"); + + await inner.click(); + await inner.keys("a"); + + await browser.waitUntil(() => respPopover.getProperty("opened"), { + timeout: 3000, + timeoutMsg: "Popover should be displayed" + }); + }); + + it("Does not reopeon picker on focus in", async () => { + const input = await $("#field"); + const inner = await input.shadow$("input"); + const staticAreaClassName = await browser.getStaticAreaItemClassName("#field"); + const respPopover = await $(`.${staticAreaClassName}`).shadow$("ui5-responsive-popover"); + + await inner.click(); + await inner.keys("a"); + + // go to next focusable + await browser.keys(["Shift", "Tab"]); + + // go to previous + await browser.keys("Tab"); + + await browser.pause(3000); + + assert.notOk(await respPopover.getProperty("opened"), "Picker should not be open"); + }); +});