From 89e3508db7a0426e52abfeca449fa589eeb4936e Mon Sep 17 00:00:00 2001 From: Vladislav Tasev Date: Thu, 20 Jun 2019 13:29:13 +0300 Subject: [PATCH] feat: add form support for ui5-select (#565) ui5-select gets "name" attribute, ui5-option gets "value" attribute BREAKING CHANGE: the parameter of the change event is now called "selectedOption"; ui5-select enforces ui5-option as children in the metadata --- docs/PublicModuleImports.md | 2 + packages/main/bundle.esm.js | 1 - packages/main/src/Button.js | 4 +- packages/main/src/CheckBox.js | 4 +- packages/main/src/DatePicker.js | 4 +- packages/main/src/Input.js | 4 +- packages/main/src/Option.js | 11 ++++ packages/main/src/RadioButton.js | 6 +-- packages/main/src/Select.hbs | 2 + packages/main/src/Select.js | 51 ++++++++++++++++--- packages/main/src/TextArea.js | 4 +- .../ui/webcomponents/main/pages/Select.html | 2 +- .../sap/ui/webcomponents/main/pages/form.html | 8 +-- 13 files changed, 76 insertions(+), 27 deletions(-) diff --git a/docs/PublicModuleImports.md b/docs/PublicModuleImports.md index 010d8e1265a9..ca858f563e04 100644 --- a/docs/PublicModuleImports.md +++ b/docs/PublicModuleImports.md @@ -29,6 +29,7 @@ For API documentation and samples, please check the [UI5 Web Components Playgrou | Popover | `ui5-popover` | `import "@ui5/webcomponents/dist/Popover.js";` | | Radio Button | `ui5-radiobutton` | `import "@ui5/webcomponents/dist/RadioButton.js";` | | Select | `ui5-select` | `import "@ui5/webcomponents/dist/Select.js";` | +| Select Option | `ui5-option` | comes with ui5-select | | Shell Bar (Fiori 3) | `ui5-shellbar` | `import "@ui5/webcomponents/dist/ShellBar.js";` | | Shell Bar Item | `ui5-shellbar-item` | `import "@ui5/webcomponents/dist/ShellBarItem.js";` | | Switch | `ui5-switch` | `import "@ui5/webcomponents/dist/Switch.js";` | @@ -224,6 +225,7 @@ If you however need to submit forms, you can import the module above and it will - ui5-checkbox - ui5-radiobutton - ui5-datepicker +- ui5-select with functionality, allowing them to be submitted in forms (provided you set their name attribute) just as any standard HTML input element would be. diff --git a/packages/main/bundle.esm.js b/packages/main/bundle.esm.js index 8fb94a25995f..5aa6c7413fb5 100644 --- a/packages/main/bundle.esm.js +++ b/packages/main/bundle.esm.js @@ -26,7 +26,6 @@ import Popover from "./dist/Popover.js"; import Panel from "./dist/Panel.js"; import RadioButton from "./dist/RadioButton.js"; import Select from "./dist/Select.js"; -import Option from "./dist/Option.js"; import ShellBar from "./dist/ShellBar.js"; import ShellBarItem from "./dist/ShellBarItem.js"; import Switch from "./dist/Switch.js"; diff --git a/packages/main/src/Button.js b/packages/main/src/Button.js index 16f5a7b3f044..c8ccf6ba2a3f 100644 --- a/packages/main/src/Button.js +++ b/packages/main/src/Button.js @@ -82,7 +82,7 @@ const metadata = { * automatically submit the nearest form element upon press. * * Important: For the submits property to have effect, you must add the following import to your project: - * import InputElementsFormSupport from "@ui5/webcomponents/dist/InputElementsFormSupport"; + * import "@ui5/webcomponents/dist/InputElementsFormSupport.js"; * * @type {boolean} * @defaultvalue false @@ -198,7 +198,7 @@ class Button extends UI5Element { onBeforeRendering() { const FormSupport = getFeature("FormSupport"); if (this.submits && !FormSupport) { - console.warn(`In order for the "submits" property to have effect, you should also: import InputElementsFormSupport from "@ui5/webcomponents/dist/InputElementsFormSupport";`); // eslint-disable-line + console.warn(`In order for the "submits" property to have effect, you should also: import "@ui5/webcomponents/dist/InputElementsFormSupport.js";`); // eslint-disable-line } } diff --git a/packages/main/src/CheckBox.js b/packages/main/src/CheckBox.js index 43254949baae..f9a59e9c2ef1 100644 --- a/packages/main/src/CheckBox.js +++ b/packages/main/src/CheckBox.js @@ -104,7 +104,7 @@ const metadata = { * Determines the name with which the ui5-checkbox will be submitted in an HTML form. * * Important: For the name property to have effect, you must add the following import to your project: - * import InputElementsFormSupport from "@ui5/webcomponents/dist/InputElementsFormSupport"; + * import "@ui5/webcomponents/dist/InputElementsFormSupport.js"; * * Note: When set, a native input HTML element * will be created inside the ui5-checkbox so that it can be submitted as @@ -214,7 +214,7 @@ class CheckBox extends UI5Element { nativeInput.value = element.checked ? "on" : ""; }); } else if (this.name) { - console.warn(`In order for the "name" property to have effect, you should also: import InputElementsFormSupport from "@ui5/webcomponents/dist/InputElementsFormSupport";`); // eslint-disable-line + console.warn(`In order for the "name" property to have effect, you should also: import "@ui5/webcomponents/dist/InputElementsFormSupport.js";`); // eslint-disable-line } } diff --git a/packages/main/src/DatePicker.js b/packages/main/src/DatePicker.js index b44418774824..f8590c73e145 100644 --- a/packages/main/src/DatePicker.js +++ b/packages/main/src/DatePicker.js @@ -122,7 +122,7 @@ const metadata = { * Determines the name with which the ui5-datepicker will be submitted in an HTML form. * * Important: For the name property to have effect, you must add the following import to your project: - * import InputElementsFormSupport from "@ui5/webcomponents/dist/InputElementsFormSupport"; + * import "@ui5/webcomponents/dist/InputElementsFormSupport.js"; * * Note: When set, a native input HTML element * will be created inside the ui5-datepicker so that it can be submitted as @@ -313,7 +313,7 @@ class DatePicker extends UI5Element { if (FormSupport) { FormSupport.syncNativeHiddenInput(this); } else if (this.name) { - console.warn(`In order for the "name" property to have effect, you should also: import InputElementsFormSupport from "@ui5/webcomponents/dist/InputElementsFormSupport";`); // eslint-disable-line + console.warn(`In order for the "name" property to have effect, you should also: import "@ui5/webcomponents/dist/InputElementsFormSupport.js";`); // eslint-disable-line } } diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index bb9f3789085e..38d7a9075cd8 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -159,7 +159,7 @@ const metadata = { * Determines the name with which the ui5-input will be submitted in an HTML form. * * Important: For the name property to have effect, you must add the following import to your project: - * import InputElementsFormSupport from "@ui5/webcomponents/dist/InputElementsFormSupport"; + * import "@ui5/webcomponents/dist/InputElementsFormSupport.js"; * * Note: When set, a native input HTML element * will be created inside the ui5-input so that it can be submitted as @@ -329,7 +329,7 @@ class Input extends UI5Element { if (FormSupport) { FormSupport.syncNativeHiddenInput(this); } else if (this.name) { - console.warn(`In order for the "name" property to have effect, you should also: import InputElementsFormSupport from "@ui5/webcomponents/dist/InputElementsFormSupport";`); // eslint-disable-line + console.warn(`In order for the "name" property to have effect, you should also: import "@ui5/webcomponents/dist/InputElementsFormSupport.js";`); // eslint-disable-line } } diff --git a/packages/main/src/Option.js b/packages/main/src/Option.js index 5203cb0cc439..325f4bb96b84 100644 --- a/packages/main/src/Option.js +++ b/packages/main/src/Option.js @@ -33,6 +33,17 @@ const metadata = { type: String, defaultValue: null, }, + + /** + * Defines the value of the ui5-select inside an HTML Form element when this ui5-option is selected. + * For more information on HTML Form support, see the name property of ui5-select. + * + * @type {string} + * @public + */ + value: { + type: String, + }, }, events: /** @lends sap.ui.webcomponents.main.Option.prototype */ {}, diff --git a/packages/main/src/RadioButton.js b/packages/main/src/RadioButton.js index 5763d678dad0..2ed7b734d444 100644 --- a/packages/main/src/RadioButton.js +++ b/packages/main/src/RadioButton.js @@ -106,7 +106,7 @@ const metadata = { * Only one radio button can be selected per group. *
* Important: For the name property to have effect when submitting forms, you must add the following import to your project: - * import InputElementsFormSupport from "@ui5/webcomponents/dist/InputElementsFormSupport"; + * import "@ui5/webcomponents/dist/InputElementsFormSupport.js"; * * Note: When set, a native input HTML element * will be created inside the ui5-radiobutton so that it can be submitted as @@ -126,7 +126,7 @@ const metadata = { * will be the value of the currently selected radio button. *
* Important: For the value property to have effect, you must add the following import to your project: - * import InputElementsFormSupport from "@ui5/webcomponents/dist/InputElementsFormSupport"; + * import "@ui5/webcomponents/dist/InputElementsFormSupport.js"; * * @type {string} * @defaultvalue: "" @@ -263,7 +263,7 @@ class RadioButton extends UI5Element { nativeInput.value = element.selected ? element.value : ""; }); } else if (this.value) { - console.warn(`In order for the "value" property to have effect, you should also: import InputElementsFormSupport from "@ui5/webcomponents/dist/InputElementsFormSupport";`); // eslint-disable-line + console.warn(`In order for the "value" property to have effect, you should also: import "@ui5/webcomponents/dist/InputElementsFormSupport.js";`); // eslint-disable-line } } diff --git a/packages/main/src/Select.hbs b/packages/main/src/Select.hbs index 32d825a4869d..cb34f7d7de27 100644 --- a/packages/main/src/Select.hbs +++ b/packages/main/src/Select.hbs @@ -37,4 +37,6 @@ class="sapWCSelectDropDownIcon" @ui5-press="{{_togglePopover}}" > + + diff --git a/packages/main/src/Select.js b/packages/main/src/Select.js index 7eea861cdf54..5cd519677a60 100644 --- a/packages/main/src/Select.js +++ b/packages/main/src/Select.js @@ -10,8 +10,10 @@ import { isShow, } from "@ui5/webcomponents-base/src/events/PseudoEvents.js"; import { getCompactSize } from "@ui5/webcomponents-base/src/Configuration.js"; +import { getFeature } from "@ui5/webcomponents-base/src/FeaturesRegistry.js"; import getEffectiveRTL from "@ui5/webcomponents-base/src/util/getEffectiveRTL.js"; import ValueState from "@ui5/webcomponents-base/src/types/ValueState.js"; +import Option from "./Option.js"; import Label from "./Label.js"; import Popover from "./Popover.js"; import List from "./List.js"; @@ -33,18 +35,18 @@ const metadata = { slots: /** @lends sap.ui.webcomponents.main.Select.prototype */ { /** - * Defines the ui5-select items. + * Defines the ui5-select options. *

- * Note: Only one selected item is allowed. - * If more than one item is defined as selected, the last one would be considered as the selected one. + * Note: Only one selected option is allowed. + * If more than one option is defined as selected, the last one would be considered as the selected one. *

* Note: Use the ui5-option component to define the desired options. - * @type {HTMLElement[]} + * @type {Option[]} * @slot * @public */ options: { - type: HTMLElement, + type: Option, multiple: true, listenFor: { include: ["*"] }, }, @@ -64,6 +66,25 @@ const metadata = { type: Boolean, }, + /** + * Determines the name with which the ui5-select will be submitted in an HTML form. + * The value of the ui5-select will be the value of the currently selected ui5-option. + * + * Important: For the name property to have effect, you must add the following import to your project: + * import "@ui5/webcomponents/dist/InputElementsFormSupport.js"; + * + * Note: When set, a native input HTML element + * will be created inside the ui5-select so that it can be submitted as + * part of an HTML form. Do not use this property unless you need to submit a form. + * + * @type {string} + * @defaultvalue "" + * @public + */ + name: { + type: String, + }, + /** * Defines the value state of ui5-select. * Available options are: None, Success, Warning and Error. @@ -99,7 +120,7 @@ const metadata = { */ change: { detail: { - selectedItem: {}, + selectedOption: {}, }, }, }, @@ -160,6 +181,7 @@ class Select extends UI5Element { onBeforeRendering() { this._syncSelection(); + this._enableFormSupport(); } get _isPickerOpen() { @@ -220,6 +242,18 @@ class Select extends UI5Element { this._syncedOptions = opts; } + _enableFormSupport() { + const FormSupport = getFeature("FormSupport"); + if (FormSupport) { + FormSupport.syncNativeHiddenInput(this, (element, nativeInput) => { + nativeInput.disabled = element.disabled; + nativeInput.value = element.selectedOption.value; + }); + } else if (this.name) { + console.warn(`In order for the "name" property to have effect, you should also: import "@ui5/webcomponents/dist/InputElementsFormSupport.js";`); // eslint-disable-line + } + } + _keydown(event) { if (isShow(event)) { this._togglePopover(); @@ -285,7 +319,7 @@ class Select extends UI5Element { this._selectedIndex = nextIndex === -1 ? this._selectedIndex : nextIndex; if (shouldFireEvent) { - this.fireEvent("change", { selectedItem: this.options[nextIndex] }); + this.fireEvent("change", { selectedOption: this.options[nextIndex] }); } } @@ -316,7 +350,7 @@ class Select extends UI5Element { this._select(this._selectedIndexBeforeOpen); this._escapePressed = false; } else if (this._lastSelectedOption !== this.options[this._selectedIndex]) { - this.fireEvent("change", { selectedItem: this.options[this._selectedIndex] }); + this.fireEvent("change", { selectedOption: this.options[this._selectedIndex] }); this._lastSelectedOption = this.options[this._selectedIndex]; } } @@ -353,6 +387,7 @@ class Select extends UI5Element { static async define(...params) { await Promise.all([ + Option.define(), Label.define(), Popover.define(), List.define(), diff --git a/packages/main/src/TextArea.js b/packages/main/src/TextArea.js index b0da39c7741f..aca3ac687a60 100644 --- a/packages/main/src/TextArea.js +++ b/packages/main/src/TextArea.js @@ -142,7 +142,7 @@ const metadata = { * Determines the name with which the ui5-textarea will be submitted in an HTML form. * * Important: For the name property to have effect, you must add the following import to your project: - * import InputElementsFormSupport from "@ui5/webcomponents/dist/InputElementsFormSupport"; + * import "@ui5/webcomponents/dist/InputElementsFormSupport.js"; * * Note: When set, a native input HTML element * will be created inside the ui5-textarea so that it can be submitted as @@ -256,7 +256,7 @@ class TextArea extends UI5Element { if (FormSupport) { FormSupport.syncNativeHiddenInput(this); } else if (this.name) { - console.warn(`In order for the "name" property to have effect, you should also: import InputElementsFormSupport from "@ui5/webcomponents/dist/InputElementsFormSupport";`); // eslint-disable-line + console.warn(`In order for the "name" property to have effect, you should also: import "@ui5/webcomponents/dist/InputElementsFormSupport.js";`); // eslint-disable-line } } diff --git a/packages/main/test/sap/ui/webcomponents/main/pages/Select.html b/packages/main/test/sap/ui/webcomponents/main/pages/Select.html index 679737525cb7..b82cffdc133f 100644 --- a/packages/main/test/sap/ui/webcomponents/main/pages/Select.html +++ b/packages/main/test/sap/ui/webcomponents/main/pages/Select.html @@ -65,7 +65,7 @@

Change event counter holder

// Select select.addEventListener("ui5-change", function(e) { - lbl.innerHTML = "selected item :: " + e.detail.selectedItem.textContent + " :: " + (++counter); + lbl.innerHTML = "selected item :: " + e.detail.selectedOption.textContent + " :: " + (++counter); inputResult.value = counter; }); diff --git a/packages/main/test/sap/ui/webcomponents/main/pages/form.html b/packages/main/test/sap/ui/webcomponents/main/pages/form.html index 13bbfe23a73f..85f4c98b94f3 100644 --- a/packages/main/test/sap/ui/webcomponents/main/pages/form.html +++ b/packages/main/test/sap/ui/webcomponents/main/pages/form.html @@ -54,9 +54,9 @@

Input type 'URL'


- Cozy - Compact - Condensed + Cozy + Compact + Condensed
@@ -106,4 +106,4 @@

Input type 'URL'

- \ No newline at end of file +