diff --git a/packages/main/cypress/specs/ToolbarSelect.cy.tsx b/packages/main/cypress/specs/ToolbarSelect.cy.tsx
index 1c07e3644ea1..5f10a2d145fe 100644
--- a/packages/main/cypress/specs/ToolbarSelect.cy.tsx
+++ b/packages/main/cypress/specs/ToolbarSelect.cy.tsx
@@ -605,6 +605,70 @@ describe("Toolbar general interaction", () => {
cy.get("[ui5-toolbar-select-option]").eq(2).should("have.attr", "selected");
cy.get("[ui5-toolbar-select-option]").eq(0).should("not.have.attr", "selected");
cy.get("[ui5-toolbar-select-option]").eq(1).should("not.have.attr", "selected");
- cy.get("ui5-select", { includeShadowDom: true }).should("have.attr", "value", "3");
+ cy.get("[ui5-toolbar]")
+ .find("[ui5-toolbar-select]")
+ .shadow()
+ .find("[ui5-select]")
+ .find("[ui5-option]")
+ .eq(2)
+ .should("have.attr", "selected");
+ });
+
+ it("Should clear the inner select when value is set to empty string after render", () => {
+ cy.mount(
+
+
+ Option 1
+ Option 2
+ Option 3
+
+
+ );
+
+ cy.document().then(doc => {
+ const select = doc.querySelector("ui5-toolbar-select") as ToolbarSelect;
+ select.value = "";
+ });
+
+ cy.get("[ui5-toolbar]")
+ .find("[ui5-toolbar-select]")
+ .shadow()
+ .find("[ui5-select]")
+ .should("have.attr", "value", "");
+ });
+
+ it("Should not let stale _value override a later programmatic selected change", () => {
+ cy.mount(
+ <>
+
+
+ Option 1
+ Option 2
+ Option 3
+
+
+
+ >
+ );
+
+ cy.get("#prog-btn").then($btn => {
+ $btn.get(0).addEventListener("click", () => {
+ const options = document.querySelectorAll("ui5-toolbar-select-option");
+ options.forEach(opt => { (opt as ToolbarSelectOption).selected = false; });
+ (document.getElementById("prog-opt3") as ToolbarSelectOption).selected = true;
+ });
+ });
+
+ cy.get("#prog-btn").realClick();
+
+ cy.get("[ui5-toolbar-select-option]").eq(2).should("have.attr", "selected");
+ cy.get("[ui5-toolbar-select-option]").eq(0).should("not.have.attr", "selected");
+ cy.get("[ui5-toolbar]")
+ .find("[ui5-toolbar-select]")
+ .shadow()
+ .find("[ui5-select]")
+ .find("[ui5-option]")
+ .eq(2)
+ .should("have.attr", "selected");
});
});
\ No newline at end of file
diff --git a/packages/main/src/ToolbarSelect.ts b/packages/main/src/ToolbarSelect.ts
index 74fde918b1ad..9049b4193b41 100644
--- a/packages/main/src/ToolbarSelect.ts
+++ b/packages/main/src/ToolbarSelect.ts
@@ -154,14 +154,22 @@ class ToolbarSelect extends ToolbarItemBase {
*/
@property()
set value(newValue: string) {
- if (this.select && this.select.value !== newValue) {
- this.select.value = newValue;
+ if (this.select) {
+ if (this.select.value !== newValue) {
+ this.select.value = newValue;
+ }
+ this._value = "";
+ } else {
+ this._value = newValue;
}
- this._value = newValue;
}
get value(): string | undefined {
- return this.select ? this.select.value : this._value;
+ if (this._value) {
+ return this._value;
+ }
+ const selectedOption = this.options.find(o => o.selected);
+ return selectedOption?.textContent || this.select?.value || "";
}
get select(): Select | null {
@@ -195,6 +203,30 @@ class ToolbarSelect extends ToolbarItemBase {
}
}
+ onBeforeRendering(): void {
+ super.onBeforeRendering();
+ let lastSelectedIndex = -1;
+ this.options.forEach((option, index) => {
+ if (option.selected) {
+ lastSelectedIndex = index;
+ }
+ });
+ this.options.forEach((option, index) => {
+ const shouldBeSelected = index === lastSelectedIndex;
+ if (option.selected !== shouldBeSelected) {
+ option.selected = shouldBeSelected;
+ }
+ });
+ }
+
+ onAfterRendering(): void {
+ super.onAfterRendering();
+ if (this._value && this.select) {
+ this.select.value = this._value;
+ this._value = "";
+ }
+ }
+
onChange(e: CustomEvent): void {
e.stopImmediatePropagation();
const selectedOptionIndex = Number(e.detail.selectedOption?.getAttribute("data-ui5-external-action-item-index"));
@@ -208,6 +240,7 @@ class ToolbarSelect extends ToolbarItemBase {
}
_syncOptions(selectedOptionIndex: number): void {
+ this._value = "";
this.options.forEach((option: ToolbarSelectOption, index: number) => {
option.selected = index === selectedOptionIndex;
});
diff --git a/packages/main/src/ToolbarSelectOption.ts b/packages/main/src/ToolbarSelectOption.ts
index 9c324c8fa70a..5443e6bebad6 100644
--- a/packages/main/src/ToolbarSelectOption.ts
+++ b/packages/main/src/ToolbarSelectOption.ts
@@ -3,7 +3,6 @@ import type { DefaultSlot } from "@ui5/webcomponents-base/dist/UI5Element.js";
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import slot from "@ui5/webcomponents-base/dist/decorators/slot-strict.js";
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
-import type ToolbarSelect from "./ToolbarSelect.js";
/**
* @class
@@ -34,32 +33,7 @@ class ToolbarSelectOption extends UI5Element {
* @public
*/
@property({ type: Boolean })
- set selected(value: boolean) {
- if (value) {
- this.setAttribute("selected", "");
- this._clearSiblingsAndSync();
- } else {
- this.removeAttribute("selected");
- }
- }
-
- get selected(): boolean {
- return this.hasAttribute("selected");
- }
-
- _clearSiblingsAndSync(): void {
- const parent = this.parentElement as ToolbarSelect;
- if (parent) {
- parent.options?.forEach(option => {
- if (option !== this) {
- option.removeAttribute("selected");
- }
- });
- if (parent.select) {
- parent.select.value = this.value !== undefined && this.value !== "" ? this.value : (this.textContent || "");
- }
- }
- }
+ selected = false;
/**
* Defines the text of the component.
diff --git a/packages/main/src/ToolbarSelectTemplate.tsx b/packages/main/src/ToolbarSelectTemplate.tsx
index b1ffef24f03b..1ac2d1384de4 100644
--- a/packages/main/src/ToolbarSelectTemplate.tsx
+++ b/packages/main/src/ToolbarSelectTemplate.tsx
@@ -7,7 +7,6 @@ export default function ToolbarSelectTemplate(this: ToolbarSelect) {