diff --git a/packages/main/cypress/specs/Input.cy.tsx b/packages/main/cypress/specs/Input.cy.tsx
index 4081a16b5e9f..a12c68ff999c 100644
--- a/packages/main/cypress/specs/Input.cy.tsx
+++ b/packages/main/cypress/specs/Input.cy.tsx
@@ -544,6 +544,79 @@ describe("Input general interaction", () => {
cy.get("@onChange").should("have.been.calledOnce");
cy.get("@onSelectionChange").should("have.been.calledOnce");
});
+
+ it("Should control suggestions dynamically based on threshold", () => {
+ const THRESHOLD = 3;
+ const countries = [
+ "Argentina", "Albania", "Algeria", "Angola", "Austria", "Australia",
+ "Bulgaria", "Belgium", "Brazil", "Canada", "Colombia", "Croatia"
+ ];
+
+ cy.mount();
+
+ cy.document().then(doc => {
+ const input = doc.querySelector("#threshold-input")!;
+
+ input.addEventListener("input", () => {
+ const value = input.value;
+
+ while (input.lastChild) {
+ input.removeChild(input.lastChild);
+ }
+
+ if (value.length >= THRESHOLD) {
+ input.showSuggestions = true;
+
+ const filtered = countries.filter(country =>
+ country.toUpperCase().indexOf(value.toUpperCase()) === 0
+ );
+
+ filtered.forEach(country => {
+ const item = document.createElement("ui5-suggestion-item");
+ item.setAttribute("text", country);
+ input.appendChild(item);
+ });
+ } else {
+ input.showSuggestions = false;
+ }
+ });
+ });
+
+ cy.get("#threshold-input")
+ .as("input")
+ .realClick();
+
+ cy.get("@input")
+ .should("be.focused");
+
+ cy.realType("B");
+
+ cy.get("@input")
+ .shadow()
+ .find("[ui5-responsive-popover]")
+ .should("not.exist", "true");
+
+ cy.realType("ul");
+
+ cy.get("@input")
+ .shadow()
+ .find("[ui5-responsive-popover]")
+ .ui5ResponsivePopoverOpened();
+
+ cy.get("@input")
+ .find("[ui5-suggestion-item]")
+ .should("have.length", 1)
+ .first()
+ .should("have.attr", "text", "Bulgaria");
+
+ cy.realPress("Backspace");
+ cy.realPress("Backspace");
+
+ cy.get("@input")
+ .shadow()
+ .find("[ui5-responsive-popover]")
+ .should("not.exist", "true");
+ });
});
describe("Input arrow navigation", () => {
diff --git a/packages/main/cypress/specs/Input.mobile.cy.tsx b/packages/main/cypress/specs/Input.mobile.cy.tsx
index 1549f598b846..60c97f9e96da 100644
--- a/packages/main/cypress/specs/Input.mobile.cy.tsx
+++ b/packages/main/cypress/specs/Input.mobile.cy.tsx
@@ -198,6 +198,57 @@ describe("Eventing", () => {
cy.get("@onSelectionChange").should("have.been.calledOnce");
});
+
+ it("Should control suggestions dynamically based on threshold on mobile", () => {
+ const THRESHOLD = 3;
+ const countries = [
+ "Argentina", "Albania", "Algeria", "Angola", "Austria", "Australia",
+ "Bulgaria", "Belgium", "Brazil", "Canada", "Colombia", "Croatia"
+ ];
+
+ cy.mount();
+
+ cy.document().then(doc => {
+ const input = doc.querySelector("#mobile-threshold")!;
+
+ input.addEventListener("input", () => {
+ const value = input.value;
+
+ while (input.lastChild) {
+ input.removeChild(input.lastChild);
+ }
+
+ if (value.length >= THRESHOLD) {
+ input.showSuggestions = true;
+
+ const filtered = countries.filter(country =>
+ country.toUpperCase().indexOf(value.toUpperCase()) === 0
+ );
+
+ filtered.forEach(country => {
+ const item = document.createElement("ui5-suggestion-item");
+ item.setAttribute("text", country);
+ input.appendChild(item);
+ });
+ } else {
+ input.showSuggestions = false;
+ }
+ });
+ });
+
+ cy.get("#mobile-threshold")
+ .as("input")
+ .realClick();
+
+ cy.get("@input")
+ .shadow()
+ .find("[ui5-responsive-popover]")
+ .ui5ResponsivePopoverOpened();
+
+ cy.get("@input").shadow().find(".ui5-input-inner-phone").should("be.focused");
+ cy.get("@input").shadow().find(".ui5-input-inner-phone").realType("Bu");
+ cy.get("@input").shadow().find("ui5-suggestion-item").should("have.length", 0);
+ });
});
describe("Typeahead", () => {
@@ -390,4 +441,4 @@ describe("Property open", () => {
.find("[ui5-responsive-popover]")
.ui5ResponsivePopoverClosed();
});
-});
\ No newline at end of file
+});
diff --git a/packages/main/src/Input.ts b/packages/main/src/Input.ts
index 0b45e9194712..8446558e93b7 100644
--- a/packages/main/src/Input.ts
+++ b/packages/main/src/Input.ts
@@ -1110,7 +1110,7 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
_onfocusout(e: FocusEvent) {
const toBeFocused = e.relatedTarget as HTMLElement;
- if (this.Suggestions?._getPicker().contains(toBeFocused) || this.contains(toBeFocused) || this.getSlottedNodes("valueStateMessage").some(el => el.contains(toBeFocused))) {
+ if (this.Suggestions?._getPicker()?.contains(toBeFocused) || this.contains(toBeFocused) || this.getSlottedNodes("valueStateMessage").some(el => el.contains(toBeFocused))) {
return;
}
@@ -1174,7 +1174,7 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
if (this.previousValue !== this.getInputDOMRefSync()!.value) {
// if picker is open there might be a selected item, wait next tick to get the value applied
- if (this.Suggestions?._getPicker().open && this._flattenItems.some(item => item.hasAttribute("ui5-suggestion-item") && (item as SuggestionItem).selected)) {
+ if (this.Suggestions?._getPicker()?.open && this._flattenItems.some(item => item.hasAttribute("ui5-suggestion-item") && (item as SuggestionItem).selected)) {
this._changeToBeFired = true;
} else {
fireChange();
@@ -1566,15 +1566,21 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
getInputDOMRef() {
if (isPhone() && this.Suggestions) {
- return this.Suggestions._getPicker()!.querySelector(".ui5-input-inner-phone")!;
+ const picker = this.Suggestions._getPicker();
+ if (picker) {
+ return picker.querySelector(".ui5-input-inner-phone")!;
+ }
}
return this.nativeInput;
}
getInputDOMRefSync() {
- if (isPhone() && this.Suggestions?._getPicker()) {
- return this.Suggestions._getPicker().querySelector(".ui5-input-inner-phone")!.shadowRoot!.querySelector("input")!;
+ if (isPhone() && this.Suggestions) {
+ const picker = this.Suggestions._getPicker();
+ if (picker) {
+ return picker.querySelector(".ui5-input-inner-phone")!.shadowRoot!.querySelector("input")!;
+ }
}
return this.nativeInput;
diff --git a/packages/main/src/features/InputSuggestionsTemplate.tsx b/packages/main/src/features/InputSuggestionsTemplate.tsx
index bd3d917370fa..6bb959dbc065 100644
--- a/packages/main/src/features/InputSuggestionsTemplate.tsx
+++ b/packages/main/src/features/InputSuggestionsTemplate.tsx
@@ -72,7 +72,7 @@ export default function InputSuggestionsTemplate(this: Input, hooks?: { suggesti
}
- { suggestionsList.call(this) }
+ { this.showSuggestions && suggestionsList.call(this) }
{this._isPhone &&
+
+
+
+
+
+
+
diff --git a/packages/website/docs/_components_pages/main/Input/Input.mdx b/packages/website/docs/_components_pages/main/Input/Input.mdx
index 931b34c319c6..44ed37fd75c7 100644
--- a/packages/website/docs/_components_pages/main/Input/Input.mdx
+++ b/packages/website/docs/_components_pages/main/Input/Input.mdx
@@ -6,6 +6,7 @@ import Basic from "../../../_samples/main/Input/Basic/Basic.md";
import Suggestions from "../../../_samples/main/Input/Suggestions/Suggestions.md";
import ClearIcon from "../../../_samples/main/Input/ClearIcon/ClearIcon.md";
import SuggestionsWrapping from "../../../_samples/main/Input/SuggestionsWrapping/SuggestionsWrapping.md";
+import DynamicSuggestions from "../../../_samples/main/Input/DynamicSuggestions/DynamicSuggestions.md";
import ValueStateMessage from "../../../_samples/main/Input/ValueStateMessage/ValueStateMessage.md";
import Label from "../../../_samples/main/Input/Label/Label.md";
import ValueHelpDialog from "../../../_samples/main/Input/ValueHelpDialog/ValueHelpDialog.md";
@@ -37,6 +38,12 @@ The sample demonstrates how the text of the suggestions wrap when too long.
+### Dynamic Suggestion Control
+This sample demonstrates how applications can control when suggestions appear by dynamically toggling the showSuggestions property.
+In this example, suggestions are only shown when the user has typed 3 or more characters.
+
+
+
### Input and Label
diff --git a/packages/website/docs/_samples/main/Input/DynamicSuggestions/DynamicSuggestions.md b/packages/website/docs/_samples/main/Input/DynamicSuggestions/DynamicSuggestions.md
new file mode 100644
index 000000000000..17798ecc59ab
--- /dev/null
+++ b/packages/website/docs/_samples/main/Input/DynamicSuggestions/DynamicSuggestions.md
@@ -0,0 +1,4 @@
+import html from '!!raw-loader!./sample.html';
+import js from '!!raw-loader!./main.js';
+
+
diff --git a/packages/website/docs/_samples/main/Input/DynamicSuggestions/main.js b/packages/website/docs/_samples/main/Input/DynamicSuggestions/main.js
new file mode 100644
index 000000000000..f77fbb3a0297
--- /dev/null
+++ b/packages/website/docs/_samples/main/Input/DynamicSuggestions/main.js
@@ -0,0 +1,45 @@
+import "@ui5/webcomponents/dist/Input.js";
+import "@ui5/webcomponents/dist/SuggestionItem.js";
+import "@ui5/webcomponents/dist/features/InputSuggestions.js";
+
+const THRESHOLD = 3;
+
+const countries = [
+ "Argentina", "Albania", "Algeria", "Angola", "Austria", "Australia",
+ "Bulgaria", "Belgium", "Brazil", "Canada", "Columbia", "Croatia",
+ "Denmark", "England", "Finland", "France", "Germany", "Greece",
+ "Hungary", "Ireland", "Italy", "Japan", "Kuwait", "Luxembourg",
+ "Mexico", "Morocco", "Netherlands", "Norway", "Paraguay", "Philippines",
+ "Portugal", "Romania", "Spain", "Sweden", "Switzerland", "Sri Lanka",
+ "Senegal", "Thailand", "The United Kingdom of Great Britain and Northern Ireland",
+ "USA", "Ukraine", "Vietnam"
+];
+
+let suggestionItems = [];
+
+const input = document.getElementById("input-threshold-3");
+
+input.addEventListener("input", () => {
+ const value = input.value;
+
+ // Clear existing suggestions
+ while (input.lastChild) {
+ input.removeChild(input.lastChild);
+ }
+
+ if (value.length >= THRESHOLD) {
+ // Enable suggestions and typeahead when threshold is met
+ input.showSuggestions = true;
+
+ // Filter and add matching suggestions
+ suggestionItems = countries.filter((item) => {
+ return item.toUpperCase().indexOf(value.toUpperCase()) === 0;
+ });
+
+ suggestionItems.forEach((item) => {
+ const li = document.createElement("ui5-suggestion-item");
+ li.text = item;
+ input.appendChild(li);
+ });
+ }
+});
diff --git a/packages/website/docs/_samples/main/Input/DynamicSuggestions/sample.html b/packages/website/docs/_samples/main/Input/DynamicSuggestions/sample.html
new file mode 100644
index 000000000000..1977d64e40f9
--- /dev/null
+++ b/packages/website/docs/_samples/main/Input/DynamicSuggestions/sample.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
Sample
+
+
+
+
+