diff --git a/packages/main/src/MultiComboBox.hbs b/packages/main/src/MultiComboBox.hbs
index d1f820b0e399..ed875e7ea43d 100644
--- a/packages/main/src/MultiComboBox.hbs
+++ b/packages/main/src/MultiComboBox.hbs
@@ -63,7 +63,8 @@
input-icon
slot="icon"
tabindex="-1"
- @click={{togglePopover}}
+ @click="{{togglePopover}}"
+ @mousedown="{{_onIconMousedown}}"
?pressed="{{open}}"
dir="{{effectiveDir}}"
accessible-name="{{_iconAccessibleNameText}}"
diff --git a/packages/main/src/MultiComboBox.js b/packages/main/src/MultiComboBox.js
index c61cc9193053..47c9432f9c1b 100644
--- a/packages/main/src/MultiComboBox.js
+++ b/packages/main/src/MultiComboBox.js
@@ -1,5 +1,6 @@
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
+import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js";
import {
isShow,
@@ -9,6 +10,7 @@ import {
isLeft,
isRight,
} from "@ui5/webcomponents-base/dist/Keys.js";
+import Integer from "@ui5/webcomponents-base/dist/types/Integer.js";
import "@ui5/webcomponents-icons/dist/icons/slim-arrow-down.js";
import { isIE, isPhone } from "@ui5/webcomponents-base/dist/Device.js";
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
@@ -32,6 +34,7 @@ import {
TOKENIZER_ARIA_CONTAIN_SEVERAL_TOKENS,
INPUT_SUGGESTIONS_TITLE,
ICON_ACCESSIBLE_NAME,
+ MULTICOMBOBOX_DIALOG_OK_BUTTON,
} from "./generated/i18n/i18n-defaults.js";
// Templates
@@ -41,6 +44,7 @@ import MultiComboBoxPopoverTemplate from "./generated/templates/MultiComboBoxPop
// Styles
import styles from "./generated/themes/MultiComboBox.css.js";
import ResponsivePopoverCommonCss from "./generated/themes/ResponsivePopoverCommon.css.js";
+import ValueStateMessageCss from "./generated/themes/ValueStateMessage.css.js";
/**
* @public
@@ -82,6 +86,22 @@ const metadata = {
type: HTMLElement,
},
+ /**
+ * Defines the value state message that will be displayed as pop up under the ui5-multicombobox
.
+ *
+ *
+ * Note: If not specified, a default text (in the respective language) will be displayed.
+ *
+ * Note: The valueStateMessage
would be displayed,
+ * when the ui5-select
is in Information
, Warning
or Error
value state.
+ * @type {HTMLElement[]}
+ * @since 1.0.0-rc.9
+ * @slot
+ * @public
+ */
+ valueStateMessage: {
+ type: HTMLElement,
+ },
},
properties: /** @lends sap.ui.webcomponents.main.MultiComboBox.prototype */ {
/**
@@ -205,6 +225,22 @@ const metadata = {
_rootFocused: {
type: Boolean,
},
+
+ _iconPressed: {
+ type: Boolean,
+ noAttribute: true,
+ },
+
+ _inputWidth: {
+ type: Integer,
+ noAttribute: true,
+ },
+
+ _listWidth: {
+ type: Integer,
+ defaultValue: 0,
+ noAttribute: true,
+ },
},
events: /** @lends sap.ui.webcomponents.main.MultiComboBox.prototype */ {
/**
@@ -319,7 +355,7 @@ class MultiComboBox extends UI5Element {
}
static get staticAreaStyles() {
- return ResponsivePopoverCommonCss;
+ return [ResponsivePopoverCommonCss, ValueStateMessageCss];
}
static get dependencies() {
@@ -344,6 +380,19 @@ class MultiComboBox extends UI5Element {
this._deleting = false;
this._validationTimeout = null;
this.i18nBundle = getI18nBundle("@ui5/webcomponents");
+ this._handleResizeBound = this._handleResize.bind(this);
+ }
+
+ onEnterDOM() {
+ ResizeHandler.register(this, this._handleResizeBound);
+ }
+
+ onExitDOM() {
+ ResizeHandler.deregister(this, this._handleResizeBound);
+ }
+
+ _handleResize() {
+ this._inputWidth = this.offsetWidth;
}
_inputChange() {
@@ -605,6 +654,7 @@ class MultiComboBox extends UI5Element {
this.blur();
}
+ this._iconPressed = false;
this.filterSelected = false;
}
@@ -622,14 +672,51 @@ class MultiComboBox extends UI5Element {
async onAfterRendering() {
await this._getRespPopover();
+ await this._getList();
+
+ this.toggle(this.shouldDisplayOnlyValueStateMessage);
+ this.storeResponsivePopoverWidth();
}
- get valueStateTextMappings() {
- return {
- "Success": this.i18nBundle.getText(VALUE_STATE_SUCCESS),
- "Error": this.i18nBundle.getText(VALUE_STATE_ERROR),
- "Warning": this.i18nBundle.getText(VALUE_STATE_WARNING),
- };
+ get _isPhone() {
+ return isPhone();
+ }
+
+ _onIconMousedown() {
+ this._iconPressed = true;
+ }
+
+ storeResponsivePopoverWidth() {
+ if (this.open && !this._listWidth) {
+ this._listWidth = this.list.offsetWidth;
+ }
+ }
+
+ toggle(isToggled) {
+ if (isToggled && !this.open) {
+ this.openPopover();
+ } else {
+ this.closePopover();
+ }
+ }
+
+ async openPopover() {
+ const popover = await this._getPopover();
+
+ if (popover) {
+ popover.openBy(this);
+ }
+ }
+
+ async closePopover() {
+ const popover = await this._getPopover();
+
+ popover && popover.close();
+ }
+
+ async _getPopover() {
+ const staticAreaItem = await this.getStaticAreaItemDomRef();
+ return staticAreaItem.querySelector("[ui5-popover]");
}
get _tokenizer() {
@@ -674,6 +761,10 @@ class MultiComboBox extends UI5Element {
return this.valueState !== ValueState.None;
}
+ get hasValueStateMessage() {
+ return this.hasValueState && this.valueState !== ValueState.Success;
+ }
+
get valueStateText() {
return this.valueStateTextMappings[this.valueState];
}
@@ -682,6 +773,26 @@ class MultiComboBox extends UI5Element {
return this.hasValueState ? `${this._id}-valueStateDesc` : undefined;
}
+ get valueStateMessageText() {
+ return this.getSlottedNodes("valueStateMessage").map(el => el.cloneNode(true));
+ }
+
+ get shouldDisplayDefaultValueStateMessage() {
+ return !this.valueStateMessage.length && this.hasValueStateMessage;
+ }
+
+ get shouldDisplayOnlyValueStateMessage() {
+ return this._rootFocused && this.hasValueStateMessage && !this._iconPressed;
+ }
+
+ get valueStateTextMappings() {
+ return {
+ "Success": this.i18nBundle.getText(VALUE_STATE_SUCCESS),
+ "Error": this.i18nBundle.getText(VALUE_STATE_ERROR),
+ "Warning": this.i18nBundle.getText(VALUE_STATE_WARNING),
+ };
+ }
+
get _innerInput() {
if (isPhone()) {
if (this.allItemsPopover.opened) {
@@ -700,10 +811,40 @@ class MultiComboBox extends UI5Element {
return this.i18nBundle.getText(ICON_ACCESSIBLE_NAME);
}
+ get _dialogOkButton() {
+ return this.i18nBundle.getText(MULTICOMBOBOX_DIALOG_OK_BUTTON);
+ }
+
get _tokenizerExpanded() {
return this._rootFocused || this.open;
}
+ get classes() {
+ return {
+ popoverValueState: {
+ "ui5-valuestatemessage-root": true,
+ "ui5-valuestatemessage--success": this.valueState === ValueState.Success,
+ "ui5-valuestatemessage--error": this.valueState === ValueState.Error,
+ "ui5-valuestatemessage--warning": this.valueState === ValueState.Warning,
+ "ui5-valuestatemessage--information": this.valueState === ValueState.Information,
+ },
+ };
+ }
+
+ get styles() {
+ return {
+ popoverValueStateMessage: {
+ "width": `${this._listWidth}px`,
+ "min-height": "2.5rem",
+ "padding": "0.5625rem 1rem",
+ "display": this._listWidth === 0 ? "none" : "inline-block",
+ },
+ popoverHeader: {
+ "width": `${this._inputWidth}px`,
+ },
+ };
+ }
+
static async onDefine() {
await fetchI18nBundle("@ui5/webcomponents");
}
diff --git a/packages/main/src/MultiComboBoxPopover.hbs b/packages/main/src/MultiComboBoxPopover.hbs
index 163bffe74944..3a410f6fc266 100644
--- a/packages/main/src/MultiComboBoxPopover.hbs
+++ b/packages/main/src/MultiComboBoxPopover.hbs
@@ -4,24 +4,24 @@
class="ui5-multi-combobox-all-items-responsive-popover"
no-arrow
_disable-initial-focus
- content-only-on-desktop
@ui5-selection-change={{_listSelectionChange}}
@ui5-after-close={{_toggle}}
@ui5-after-open={{_toggle}}
>
-