Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions packages/main/cypress/specs/ComboBox.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2974,6 +2974,60 @@ describe("ComboBox Composition", () => {
});
});

describe("Loading State", () => {
it("should display busy indicator when loading is true", () => {
cy.mount(
<ComboBox loading open>
<ComboBoxItem text="Item 1" />
<ComboBoxItem text="Item 2" />
</ComboBox>
);

cy.get("[ui5-combobox]")
.shadow()
.find("ui5-responsive-popover")
.as("popover");

cy.get("@popover")
.find("ui5-busy-indicator")
.should("exist");

cy.get("@popover")
.find("ui5-list")
.should("not.exist");
});

it("should hide busy indicator and show items when loading becomes false", () => {
cy.mount(
<ComboBox loading open>
<ComboBoxItem text="Item 1" />
<ComboBoxItem text="Item 2" />
</ComboBox>
);

cy.get("[ui5-combobox]")
.as("combo")
.shadow()
.find("ui5-responsive-popover")
.as("popover");

cy.get("@popover")
.find("ui5-busy-indicator")
.should("exist");

cy.get("@combo")
.invoke("prop", "loading", false);

cy.get("@popover")
.find("ui5-busy-indicator")
.should("not.exist");

cy.get("@popover")
.find("ui5-list")
.should("exist");
});
});

describe("Validation inside a form", () => {
it("has correct validity for valueMissing", () => {
cy.mount(
Expand Down
54 changes: 54 additions & 0 deletions packages/main/cypress/specs/MultiComboBox.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4442,6 +4442,60 @@ describe("MultiComboBox Composition", () => {
});
});

describe("Loading State", () => {
it("should display busy indicator when loading is true", () => {
cy.mount(
<MultiComboBox loading open>
<MultiComboBoxItem text="Item 1" />
<MultiComboBoxItem text="Item 2" />
</MultiComboBox>
);

cy.get("[ui5-multi-combobox]")
.shadow()
.find("ui5-responsive-popover")
.as("popover");

cy.get("@popover")
.find("ui5-busy-indicator")
.should("exist");

cy.get("@popover")
.find("ui5-list")
.should("not.exist");
});

it("should hide busy indicator and show items when loading becomes false", () => {
cy.mount(
<MultiComboBox loading open>
<MultiComboBoxItem text="Item 1" />
<MultiComboBoxItem text="Item 2" />
</MultiComboBox>
);

cy.get("[ui5-multi-combobox]")
.as("mcb")
.shadow()
.find("ui5-responsive-popover")
.as("popover");

cy.get("@popover")
.find("ui5-busy-indicator")
.should("exist");

cy.get("@mcb")
.invoke("prop", "loading", false);

cy.get("@popover")
.find("ui5-busy-indicator")
.should("not.exist");

cy.get("@popover")
.find("ui5-list")
.should("exist");
});
});

describe("Validation inside a form", () => {
it("has correct validity for valueMissing", () => {
cy.mount(
Expand Down
8 changes: 5 additions & 3 deletions packages/main/src/ComboBoxPopoverTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ export default function ComboBoxPopoverTemplate(this: ComboBox) {
onKeyDown={this._handlePopoverKeydown}
onFocusOut={this._handlePopoverFocusout}
>
<BusyIndicator active={this.loading} class="ui5-combobox-busy"/>
{this.loading &&
<BusyIndicator active={true} class="ui5-combobox-busy"/>
}

{this._isPhone &&
{!this.loading && this._isPhone &&
<>
<div slot="header" class="ui5-responsive-popover-header">
<div class="row">
Expand Down Expand Up @@ -79,7 +81,7 @@ export default function ComboBoxPopoverTemplate(this: ComboBox) {
</div>
}

{!!this._filteredItems.length &&
{!this.loading && !!this._filteredItems.length &&
<List
class="ui5-combobox-items-list"
separators="None"
Expand Down
12 changes: 10 additions & 2 deletions packages/main/src/MultiComboBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,14 @@ class MultiComboBox extends UI5Element implements IFormInputElement {
@property({ type: Boolean })
required = false;

/**
* Indicates whether a loading indicator should be shown in the picker.
* @default false
* @public
*/
@property({ type: Boolean })
loading = false;

/**
* Defines the filter type of the component.
* @default "StartsWithPerTerm"
Expand Down Expand Up @@ -1868,8 +1876,8 @@ class MultiComboBox extends UI5Element implements IFormInputElement {
}

storeResponsivePopoverWidth() {
if (this.open && !this._listWidth) {
this._listWidth = this.list!.offsetWidth;
if (this.open && !this._listWidth && this.list) {
this._listWidth = this.list.offsetWidth;
}
}

Expand Down
13 changes: 9 additions & 4 deletions packages/main/src/MultiComboBoxPopoverTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import List from "./List.js";
import PopoverHorizontalAlign from "./types/PopoverHorizontalAlign.js";
import Popover from "./Popover.js";
import CheckBox from "./CheckBox.js";
import BusyIndicator from "./BusyIndicator.js";

export default function MultiComboBoxPopoverTemplate(this: MultiComboBox) {
return (<>
Expand All @@ -31,7 +32,11 @@ export default function MultiComboBoxPopoverTemplate(this: MultiComboBox) {
open={this.open}
opener={this}
>
{this._isPhone && <>
{this.loading &&
<BusyIndicator active={true} class="ui5-multi-combobox-busy"/>
}

{!this.loading && this._isPhone && <>
<div slot="header" class="ui5-responsive-popover-header" style={this.styles.popoverHeader}>
<div class="row">
<span>{this._headerTitleText}</span>
Expand Down Expand Up @@ -70,7 +75,7 @@ export default function MultiComboBoxPopoverTemplate(this: MultiComboBox) {
{selectAllWrapper.call(this)}
</>}

{!this._isPhone && <>
{!this.loading && !this._isPhone && <>
{this.hasValueStateMessage &&
<div slot="header" onKeyDown={this._onListHeaderKeydown} class={this.classes.responsivePopoverHeaderValueState} style={this.styles.popoverValueStateMessage}>
<Icon class="ui5-input-value-state-message-icon" name={this._valueStateMessageIcon}></Icon>
Expand All @@ -81,11 +86,11 @@ export default function MultiComboBoxPopoverTemplate(this: MultiComboBox) {
{selectAllWrapper.call(this)}
</>}

{this.filterSelected ?
{!this.loading && this.filterSelected ?
<List separators="None" selectionMode="Multiple" class="ui5-multi-combobox-all-items-list" accessibleRole="ListBox">
{this.selectedItems.map(item => <slot name={item._individualSlot}></slot>)}
</List>
:
: !this.loading &&
<List separators="None" selectionMode="Multiple" class="ui5-multi-combobox-all-items-list" accessibleRole="ListBox" onKeyDown={this._onItemKeydown}>
{this._filteredItems.map(item => <slot name={item._individualSlot}></slot>)}
</List>
Expand Down
17 changes: 17 additions & 0 deletions packages/main/src/themes/MultiComboBoxPopover.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,23 @@
max-width: inherit;
}

.ui5-multi-combobox-busy {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
z-index: 42;
display: flex;
justify-content: center;
align-items: center;
pointer-events: all;
width: 100%;
}

.ui5-multi-combobox-busy:not([active]) {
display: none;
}

[ui5-responsive-popover] [ui5-input] {
width: 100%;
}
21 changes: 20 additions & 1 deletion packages/main/test/pages/ComboBox.html
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,20 @@
SelectionChange call count: <span id="selection-change-count">0</span><br>
</div>

<div class="demo-section">
<span>Toggle Loading State</span>

<br />
<br />

<ui5-combobox id="toggle-loading-cb" class="combobox2auto">
<ui5-cb-item text="Item 1"></ui5-cb-item>
<ui5-cb-item text="Item 2"></ui5-cb-item>
<ui5-cb-item text="Item 3"></ui5-cb-item>
</ui5-combobox>
<ui5-button id="toggle-loading-btn">Toggle Loading</ui5-button>
</div>

<div class="demo-section">
<span>Lazy Loading - example does not work on IE11</span>

Expand Down Expand Up @@ -604,8 +618,13 @@ <h3>ComboBox Composition</h3>
document.getElementById("combo-focus").addEventListener("click", function () {
document.getElementById("combo").focus();
});

document.getElementById("toggle-loading-btn").addEventListener("click", function () {
const combo = document.getElementById("toggle-loading-cb");
combo.loading = !combo.loading;
});
</script>

</body>

</html>
</html>
22 changes: 21 additions & 1 deletion packages/main/test/pages/MultiComboBox.html
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,21 @@ <h3>MultiComboBox in Compact</h3>
</ui5-multi-combobox>
</div>

<div class="demo-section">
<ui5-label>Toggle Loading State:</ui5-label>
<br />
<br />

<ui5-multi-combobox id="toggle-loading-mcb">
<ui5-mcb-item text="Item 1"></ui5-mcb-item>
<ui5-mcb-item text="Item 2"></ui5-mcb-item>
<ui5-mcb-item text="Item 3"></ui5-mcb-item>
</ui5-multi-combobox>
<br /><br />

<ui5-button id="toggle-loading-btn">Toggle Loading</ui5-button>
</div>

<div class="demo-section">
<span>Placeholder test</span>

Expand Down Expand Up @@ -816,8 +831,13 @@ <h3>MultiComboBox in Compact</h3>
e.preventDefault();
document.getElementById("mcb-form-submit").textContent = ++submitCounter;
});

document.getElementById("toggle-loading-btn").addEventListener("click", function () {
const mcb = document.getElementById("toggle-loading-mcb");
mcb.loading = !mcb.loading;
});
</script>

</body>

</html>
</html>
Loading