diff --git a/packages/main/cypress/specs/Input.cy.tsx b/packages/main/cypress/specs/Input.cy.tsx index 4081a16b5e9f..5b21672b66fc 100644 --- a/packages/main/cypress/specs/Input.cy.tsx +++ b/packages/main/cypress/specs/Input.cy.tsx @@ -491,19 +491,19 @@ describe("Input general interaction", () => { ); cy.get("#input-equal-click") - .shadow() - .find("input") - .click() - .realType("Cozy"); + .shadow() + .find("input") + .click() + .realType("Cozy"); cy.get("#input-equal-click") - .shadow() - .find("[ui5-responsive-popover]") - .ui5ResponsivePopoverOpened(); + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); cy.get('#input-equal-click') - .find('ui5-suggestion-item[text="Cozy"]') - .click(); + .find('ui5-suggestion-item[text="Cozy"]') + .click(); cy.get("#input-equal-click").should("have.value", "Cozy"); cy.get("@onChange").should("have.been.calledOnce"); @@ -527,15 +527,15 @@ describe("Input general interaction", () => { ); cy.get("#input-equal-keyboard") - .shadow() - .find("input") - .click() - .realType("Cozy"); + .shadow() + .find("input") + .click() + .realType("Cozy"); cy.get("#input-equal-keyboard") - .shadow() - .find("[ui5-responsive-popover]") - .ui5ResponsivePopoverOpened(); + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); cy.realPress("ArrowDown"); cy.realPress("Enter"); @@ -821,7 +821,7 @@ describe("Input Ctrl + Alt + F8 navigation", () => { .should("have.focus"); cy.get("@secondLink") - .realPress("Tab"); + .realPress("Tab"); cy.get("@secondInput") .should("have.focus"); @@ -1582,9 +1582,9 @@ describe("Input general interaction", () => { // Mount Input with suggestions and a change event spy cy.mount( @@ -1798,7 +1798,7 @@ describe("Input general interaction", () => { .find("input") .should("not.have.attr", "aria-describedby"); }); - + it("Checks if aria-label is reflected in the shadow DOM", () => { const accessibleName = "New cool text"; cy.mount(); @@ -1961,7 +1961,7 @@ describe("Input general interaction", () => { cy.get("#input-disabled-autocomplete").shadow().find("input").click().realType("c"); cy.get("#input-disabled-autocomplete").shadow().find("input").should("have.value", "c"); }); - + it("Tests disabled autocomplete(type-ahead)", () => { cy.mount( @@ -1999,9 +1999,9 @@ describe("Input general interaction", () => { cy.get("#inputPreview2").shadow().find("input").click().realType("c"); cy.get("#inputPreview2") - .shadow() - .find("[ui5-responsive-popover]") - .ui5ResponsivePopoverOpened(); + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); cy.get("#inputPreview2").shadow().find("input").realPress("ArrowDown"); @@ -2020,9 +2020,9 @@ describe("Input general interaction", () => { cy.get("#myInput").shadow().find("input").click().realType("a"); cy.get("#myInput") - .shadow() - .find("[ui5-responsive-popover]") - .ui5ResponsivePopoverOpened(); + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); cy.get("#myInput").shadow().find("ui5-responsive-popover").ui5ResponsivePopoverOpened(); cy.get("@onOpen").should("have.been.calledOnce"); @@ -2057,17 +2057,17 @@ describe("Input general interaction", () => { cy.get("#inputInDialog").shadow().find("input").realType("c"); cy.get("#inputInDialog") - .shadow() - .find("[ui5-responsive-popover]") - .ui5ResponsivePopoverOpened(); + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); cy.get("#inputInDialog").shadow().find("ui5-responsive-popover").ui5ResponsivePopoverOpened(); cy.get("#inputInDialog").shadow().find("input").realPress("ArrowDown"); cy.get("#inputInDialog").shadow().find("input").realPress("Escape"); cy.get("#inputInDialog") - .shadow() - .find("[ui5-responsive-popover]") - .ui5ResponsivePopoverClosed(); + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverClosed(); cy.get("#dialog").should("have.attr", "open"); }); @@ -2221,7 +2221,7 @@ describe("Input general interaction", () => { .as("popover") .ui5ResponsivePopoverOpened(); - cy.get("#openPickerInput") + cy.get("#openPickerInput") .shadow() .find("[ui5-responsive-popover]") .should("have.attr", "open"); @@ -2295,7 +2295,7 @@ describe("Input general interaction", () => { }); it("Tests prevented input event", () => { - cy.mount( (e.target as Input).value.length > 3 ? e.preventDefault() : null}/>); + cy.mount( (e.target as Input).value.length > 3 ? e.preventDefault() : null} />); cy.get("#prevent-input-event").shadow().find("input").click().realType("abcd"); cy.get("#prevent-input-event").should("have.value", "abc"); @@ -2498,9 +2498,9 @@ describe("Lazy loading", () => { cy.get("#field").shadow().find("input").click().realType("a"); cy.get("#field") - .shadow() - .find("[ui5-responsive-popover]") - .ui5ResponsivePopoverOpened(); + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); }); it("Does not reopen picker on focus in", () => { @@ -2516,9 +2516,9 @@ describe("Lazy loading", () => { cy.get("#field").shadow().find("input").realPress("Tab"); cy.wait(3000); cy.get("#field") - .shadow() - .find("[ui5-responsive-popover]") - .ui5ResponsivePopoverClosed(); + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverClosed(); }); it("Should not close picker when items are updated", () => { @@ -2531,14 +2531,14 @@ describe("Lazy loading", () => { cy.get("#field1").shadow().find("input").click().realType("S"); cy.get("#field1") - .shadow() - .find("[ui5-responsive-popover]") - .ui5ResponsivePopoverOpened(); + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); cy.get("#field1").shadow().find("input").realType("b"); cy.get("#field1") - .shadow() - .find("[ui5-responsive-popover]") - .ui5ResponsivePopoverOpened(); + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); }); }); @@ -2609,9 +2609,9 @@ describe("Property open", () => { ); cy.get("#input-suggestions-open") - .shadow() - .find("[ui5-responsive-popover]") - .ui5ResponsivePopoverOpened(); + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverOpened(); cy.get("#input-suggestions-open").find("ui5-suggestion-item").should("have.length", 3); }); @@ -2625,9 +2625,52 @@ describe("Property open", () => { ); cy.get("#input-suggestions-open") - .shadow() - .find("[ui5-responsive-popover]") - .ui5ResponsivePopoverClosed(); + .shadow() + .find("[ui5-responsive-popover]") + .ui5ResponsivePopoverClosed(); + }); + + it("should show only one valuestate popover when valueState changes during typing", () => { + cy.mount( + { + (e.target as Input).valueState = "Negative"; + }} + > + + + ); + + cy.get("#input-valuestate-dynamic") + .as("input") + .realClick(); + + cy.get("@input") + .should("be.focused"); + + cy.get("@input") + .realType("a"); + + cy.get("@input") + .should("have.attr", "value-state", "Negative"); + + cy.get("@input") + .shadow() + .find("[ui5-responsive-popover]") + .as("suggestionsPopover") + .should("have.attr", "open"); + + cy.get("@input") + .realPress("Escape"); + + cy.get("@input") + .shadow() + .find("[ui5-popover]") + .as("valueStatePopover") + .should("have.attr", "open"); }); }); @@ -2665,7 +2708,7 @@ describe("Input Composition", () => { cy.get("@input").should("have.prop", "_isComposing", true); cy.get("@nativeInput").trigger("compositionend", { data: "사랑" }); - + cy.get("@nativeInput") .invoke("val", "사랑") .trigger("input", { inputType: "insertCompositionText" }); @@ -2720,7 +2763,7 @@ describe("Input Composition", () => { cy.get("@input").should("have.prop", "_isComposing", true); cy.get("@nativeInput").trigger("compositionend", { data: "ありがとう" }); - + cy.get("@nativeInput") .invoke("val", "ありがとう") .trigger("input", { inputType: "insertCompositionText" }); @@ -2775,7 +2818,7 @@ describe("Input Composition", () => { cy.get("@input").should("have.prop", "_isComposing", true); cy.get("@nativeInput").trigger("compositionend", { data: "谢谢" }); - + cy.get("@nativeInput") .invoke("val", "谢谢") .trigger("input", { inputType: "insertCompositionText" }); diff --git a/packages/main/src/Input.ts b/packages/main/src/Input.ts index 0b45e9194712..9d10e3506c02 100644 --- a/packages/main/src/Input.ts +++ b/packages/main/src/Input.ts @@ -762,13 +762,8 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement const hasItems = !!this._flattenItems.length; const hasValue = !!this.value; const isFocused = this.shadowRoot!.querySelector("input") === getActiveElement(); - if (this.shouldDisplayOnlyValueStateMessage) { - this.openValueStatePopover(); - } else { - this.closeValueStatePopover(); - } - const preventOpenPicker = this.disabled || this.readonly; + const shouldOpenSuggestions = !preventOpenPicker && !this._isPhone && hasItems && (this.open || (hasValue && isFocused && this.isTyping)); if (preventOpenPicker) { this.open = false; @@ -776,6 +771,12 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement this.open = hasItems && (this.open || (hasValue && isFocused && this.isTyping)); } + if (this.shouldDisplayOnlyValueStateMessage && !shouldOpenSuggestions) { + this.openValueStatePopover(); + } else { + this.closeValueStatePopover(); + } + const value = this.value; const innerInput = this.getInputDOMRefSync(); @@ -980,9 +981,9 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement }); link.addEventListener("keydown", this._linksListenersArray[index]); }); - } + } - _removeLinksEventListeners() { + _removeLinksEventListeners() { const links = this.linksInAriaValueStateHiddenText; links.forEach((link, index) => { @@ -1105,7 +1106,7 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement * Called on "focusin" of the native input HTML Element. * **Note:** implemented in MultiInput, but used in the Input template. */ - innerFocusIn(): void | undefined {} + innerFocusIn(): void | undefined { } _onfocusout(e: FocusEvent) { const toBeFocused = e.relatedTarget as HTMLElement; @@ -1443,7 +1444,7 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement // If the feature is preloaded (the user manually imported InputSuggestions.js), it is already available on the constructor if (Input.SuggestionsClass) { setup(Input.SuggestionsClass); - // If feature is not preloaded, load it dynamically + // If feature is not preloaded, load it dynamically } else { import("./features/InputSuggestions.js").then(SuggestionsModule => { setup(SuggestionsModule.default); @@ -1802,7 +1803,7 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement const links: Array = []; if (this.valueStateMessage) { this.valueStateMessage.forEach(element => { - if (element.children.length) { + if (element.children.length) { element.querySelectorAll("ui5-link").forEach(link => { links.push(link as HTMLElement); }); diff --git a/packages/main/test/pages/Input.html b/packages/main/test/pages/Input.html index 4e18da99c108..b93fa4746be4 100644 --- a/packages/main/test/pages/Input.html +++ b/packages/main/test/pages/Input.html @@ -40,30 +40,30 @@

Input in Compact

-
-

Flat items

+
+

Flat items

- - -
+ + +
-
-
+
+
-
-

Custom Suggestions

+
+

Custom Suggestions

- - -
+ + +
-

Custom Suggestions Flat

+

Custom Suggestions Flat

- + -
- SelectionChange: 0 - Item index: -1 +
+ SelectionChange: 0 + Item index: -1
@@ -127,7 +127,8 @@

Input with valueState and Dynamic suggestions

Input with long suggestions with valueState and ui5-li

- + @@ -159,8 +160,10 @@

'selection-item-select' event result

Test 'input' event

-
Information message. This is a Link. Extra long text used as an - information message. Extra long text used as an information message - 2. Extra long text used as an information +
Information message. This is a Link. Extra long text + used as an + information message. Extra long text used as an information message - 2. Extra long text used as an + information message - 3.

'input' test result

@@ -263,7 +266,8 @@

Input with multiple icons

Input firing submit event and submit action on 'ENTER' in a form

- +

Test scroll pos

@@ -339,7 +343,8 @@

Input suggestions with highlighing and XSS test

Test width of suggestions popover

- +

Input in a Dialog

@@ -387,7 +392,8 @@

sap_horizon

- +

@@ -433,7 +439,8 @@

Inputs with clear icon


Input with suggestions and clear icon
- + @@ -444,7 +451,8 @@

Inputs with clear icon

Input with open suggestions on focusin

- + No recent users @@ -510,9 +518,9 @@

'select' event handling

Input - open suggestions picker

- - - + + +
@@ -534,6 +542,12 @@

Input - open suggestions picker

Input with just accessible description + ASDASDAS + + + + +

Input Composition

@@ -558,7 +572,7 @@

Input Composition

Input Composition with Chinese Suggestions
- + @@ -1113,6 +1127,11 @@

Input Composition

document.getElementById("prevent-input-event-clear-icon").addEventListener("ui5-input", event => { event.preventDefault(); }); + const inputasd = document.getElementById('inputasd'); + + inputasd.addEventListener('input', (event) => { + inputasd.valueState = 'Negative'; + });