diff --git a/packages/main/cypress/specs/MultiComboBox.cy.tsx b/packages/main/cypress/specs/MultiComboBox.cy.tsx
index cbaf5b490727..4e51fb2029e5 100644
--- a/packages/main/cypress/specs/MultiComboBox.cy.tsx
+++ b/packages/main/cypress/specs/MultiComboBox.cy.tsx
@@ -1495,18 +1495,18 @@ describe("Validation & Value State", () => {
cy.realType("4");
cy.get("@input")
- .should("have.value", "1");
+ .should("have.value", "14");
cy.get("@mcb")
.should("have.attr", "value-state", "Negative");
});
- it("Reset value state validation after 2500ms", () => {
+ it("Invalid input persists - no automatic clearing", () => {
cy.mount(
-
-
-
+
+
+
);
@@ -1517,21 +1517,73 @@ describe("Validation & Value State", () => {
cy.get("@mcb")
.should("be.focused");
- cy.realType("4");
+ cy.realType("InvalidText");
cy.get("@mcb")
.should("have.attr", "value-state", "Negative");
- cy.wait(2500);
+ cy.get("@mcb")
+ .shadow()
+ .find("input")
+ .as("input")
+ .should("have.value", "InvalidText");
+
+ // Wait to test that the value state persists after some time
+ cy.wait(2500)
+
+ cy.get("@input")
+ .should("have.value", "InvalidText");
+
+ cy.get("@mcb")
+ .should("have.attr", "value-state", "Negative");
+ });
+
+ it("Value state resets when valid entry is entered after invalid input", () => {
+ cy.mount(
+
+
+
+
+
+ );
+
+ cy.get("[ui5-multi-combobox]")
+ .as("mcb")
+ .realClick();
+
+ cy.get("@mcb")
+ .should("be.focused");
+
+ // Type invalid text
+ cy.realType("xyz");
+
+ cy.get("@mcb")
+ .should("have.attr", "value-state", "Negative");
+
+ cy.get("@mcb")
+ .shadow()
+ .find("input")
+ .as("input")
+ .should("have.value", "xyz");
+
+ // Clear and type valid text
+ cy.get("@input")
+ .clear();
+
+ cy.realType("Item");
cy.get("@mcb")
.should("have.attr", "value-state", "None");
+
+ cy.get("@input")
+ .should("have.value", "Item 1");
});
- it("Built in validation by typing a non existing option", () => {
+ it("Value state resets when input is cleared after invalid entry", () => {
cy.mount(
-
+
+
);
@@ -1542,12 +1594,64 @@ describe("Validation & Value State", () => {
cy.get("@mcb")
.should("be.focused");
- cy.realType("CCo");
+ // Type invalid text
+ cy.realType("InvalidValue");
+
+ cy.get("@mcb")
+ .should("have.attr", "value-state", "Negative");
cy.get("@mcb")
.shadow()
.find("input")
- .should("have.value", "Cosy");
+ .as("input")
+ .should("have.value", "InvalidValue");
+
+ // Clear the input
+ cy.get("@input")
+ .clear();
+
+ cy.get("@mcb")
+ .should("have.attr", "value-state", "None");
+
+ cy.get("@input")
+ .should("have.value", "");
+ });
+
+ it("Value state preserved when switching between valid and invalid", () => {
+ cy.mount(
+
+
+
+
+ );
+
+ cy.get("[ui5-multi-combobox]")
+ .as("mcb")
+ .realClick();
+
+ cy.get("@mcb")
+ .should("be.focused");
+
+ cy.get("@mcb")
+ .should("have.attr", "value-state", "Critical");
+
+ // Type invalid text
+ cy.realType("xyz");
+
+ cy.get("@mcb")
+ .should("have.attr", "value-state", "Negative");
+
+ cy.get("@mcb")
+ .shadow()
+ .find("input")
+ .as("input");
+
+ // Clear and verify original state is restored
+ cy.get("@input")
+ .clear();
+
+ cy.get("@mcb")
+ .should("have.attr", "value-state", "Critical");
});
it("Tests if item is created when enter is pressed while validation is ongoing", () => {
@@ -4214,7 +4318,6 @@ describe("MultiComboBox Composition", () => {
simulateCompositionStages(["ㄲ", "ㄲㅏ"], "까");
cy.get("@mcb").should("have.attr", "value-state", "Negative");
- cy.get("@input").should("have.value", "");
cy.get("@mcb")
.shadow()
.find("[ui5-tokenizer] [ui5-token]")
@@ -4248,7 +4351,6 @@ describe("MultiComboBox Composition", () => {
simulateCompositionStages(["ず", "ずx"], "ずx");
cy.get("@mcb").should("have.attr", "value-state", "Negative");
- cy.get("@input").should("have.value", "");
cy.get("@mcb")
.shadow()
.find("[ui5-tokenizer] [ui5-token]")
@@ -4284,7 +4386,6 @@ describe("MultiComboBox Composition", () => {
simulateCompositionStages(["p", "pi", "pin"], "品味");
cy.get("@mcb").should("have.attr", "value-state", "Negative");
- cy.get("@input").should("have.value", "");
cy.get("@mcb")
.shadow()
.find("[ui5-tokenizer] [ui5-token]")
diff --git a/packages/main/src/MultiComboBox.ts b/packages/main/src/MultiComboBox.ts
index c941d6eaf633..b538b57b1081 100644
--- a/packages/main/src/MultiComboBox.ts
+++ b/packages/main/src/MultiComboBox.ts
@@ -708,7 +708,6 @@ class MultiComboBox extends UI5Element implements IFormInputElement {
const input = e.target as HTMLInputElement;
const value: string = input.value;
const filteredItems: Array = this._filterItems(value);
- const oldValueState: `${ValueState}` = this.valueState;
this._shouldFilterItems = true;
@@ -721,24 +720,20 @@ class MultiComboBox extends UI5Element implements IFormInputElement {
this.valueState = this._effectiveValueState;
this._validationTimeout = null;
} else {
- input.value = this._inputLastValue;
return;
}
}
- this._effectiveValueState = this.valueState;
+ // Save the original value state before setting validation error
+ if (this.valueState !== ValueState.Negative) {
+ this._effectiveValueState = this.valueState;
+ }
if (!this._isComposing && !filteredItems.length && value && !this.noValidation) {
- const newValue = this.valueBeforeAutoComplete || this._inputLastValue;
-
- input.value = newValue;
- this.value = newValue;
this.valueState = ValueState.Negative;
-
this._shouldAutocomplete = false;
- this._resetValueState(oldValueState);
-
- return;
+ } else if ((filteredItems.length || !value) && this.valueState === ValueState.Negative) {
+ this.valueState = this._effectiveValueState;
}
if (!this._isComposing) {
@@ -1938,10 +1933,6 @@ class MultiComboBox extends UI5Element implements IFormInputElement {
}
this._tokenizer.expanded = this.open;
- // remove the value if user focus out the input and focus is not going in the popover
- if (!isPhone() && !this.noValidation && !focusIsGoingInPopover) {
- this.value = "";
- }
}
}
/**