From f6846633827b8fcc52dca7171269134c1d05d238 Mon Sep 17 00:00:00 2001 From: Tony Mobily Date: Sun, 28 Aug 2016 15:46:46 +0800 Subject: [PATCH 1/6] Add option to set a specific value sent to the server for each option At the moment, if you have a dropdown menu like this: Italy France Other After submitting, the server will receive "Italy", "France" or "". There is no way, at the moment, for it to behave like a native select box: The only option to send the right data to the server is by setting the "label" attribute for the various elements. However, this has the side effect that after making the selection, the user will see "it", "fr" etc. This patch addresses that: if `value` is set for the selected item, THAT is the value considered and assigned to the paper-dropdown-menu. I wouldn't have tortured you with a PR if I had found a way to do this in other ways... sorry! --- paper-dropdown-menu.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/paper-dropdown-menu.html b/paper-dropdown-menu.html index d34221d..1523cc2 100644 --- a/paper-dropdown-menu.html +++ b/paper-dropdown-menu.html @@ -346,14 +346,14 @@ */ _selectedItemChanged: function(selectedItem) { var value = ''; - if (!selectedItem) { - value = ''; - } else { - value = selectedItem.label || selectedItem.getAttribute('label') || selectedItem.textContent.trim(); + var labelValue = ''; + if (selectedItem) { + value = selectedItem.getAttribute('value') || selectedItem.label || selectedItem.getAttribute('label') || selectedItem.textContent.trim(); + labelValue = selectedItem.label || selectedItem.getAttribute('label') || selectedItem.textContent.trim(); } this._setValue(value); - this._setSelectedItemLabel(value); + this._setSelectedItemLabel(labelValue); }, /** From 7280cd53f873dc8d8d77c6b9d9651d41ae701524 Mon Sep 17 00:00:00 2001 From: Tony Mobily Date: Wed, 31 Aug 2016 11:13:58 +0800 Subject: [PATCH 2/6] Added documentation, and fixed the code slightly --- paper-dropdown-menu.html | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/paper-dropdown-menu.html b/paper-dropdown-menu.html index 1523cc2..07721c4 100644 --- a/paper-dropdown-menu.html +++ b/paper-dropdown-menu.html @@ -31,6 +31,10 @@ item is displayed in the control. If no item is selected, the `label` is displayed instead. +Selected items can specify a `value` attribute, which will be assigned to the +`paper-dropdown-menu`'s' own `value` (just like it happens in native select forms). + + Example: @@ -42,7 +46,16 @@ -This example renders a dropdown menu with 4 options. +Or, specifiing values, especially useful in forms: + + + + United Kingdom + United states of America + Italy + Spain + + The child element with the class `dropdown-content` is used as the dropdown menu. This can be a [`paper-listbox`](paper-listbox), or any other or @@ -70,7 +83,7 @@ `--paper-dropdown-menu-input` | A mixin that is applied to the internal paper input | `{}` `--paper-dropdown-menu-icon` | A mixin that is applied to the internal icon | `{}` -You can also use any of the `paper-input-container` and `paper-menu-button` +You ca/n also use any of the `paper-input-container` and `paper-menu-button` style mixins and custom properties to style the internal input and menu button respectively. @@ -160,8 +173,9 @@ /** * The value for this element that will be used when submitting in - * a form. It is read only, and will always have the same value - * as `selectedItemLabel`. + * a form. It is read only, and will be equal to the 'value' attribute + * of the selected item, or (as a fallback) will be the same as + * `selectedItemLabel`. */ value: { type: String, @@ -339,7 +353,9 @@ }, /** - * Compute the label for the dropdown given a selected item. + * Compute the value and the label for the dropdown given a selected item. + * The selected item's `value` (if available) is used as the dropdown + * menu's own value. As a fallback, the label is used. * * @param {Element} selectedItem A selected Element item, with an * optional `label` property. @@ -348,8 +364,9 @@ var value = ''; var labelValue = ''; if (selectedItem) { - value = selectedItem.getAttribute('value') || selectedItem.label || selectedItem.getAttribute('label') || selectedItem.textContent.trim(); labelValue = selectedItem.label || selectedItem.getAttribute('label') || selectedItem.textContent.trim(); + value = selectedItem.getAttribute('value') || selectedItem.value; + value = ( value || value === '') ? value : labelValue; } this._setValue(value); From 95411bec388eaca9baa4352a59e64288cf866f6a Mon Sep 17 00:00:00 2001 From: Tony Mobily Date: Wed, 31 Aug 2016 14:15:25 +0800 Subject: [PATCH 3/6] Fixed the logix, since '' is falsy in JS but '' (empty str) should be allowed as value --- paper-dropdown-menu.html | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/paper-dropdown-menu.html b/paper-dropdown-menu.html index 07721c4..022bc31 100644 --- a/paper-dropdown-menu.html +++ b/paper-dropdown-menu.html @@ -365,10 +365,13 @@ var labelValue = ''; if (selectedItem) { labelValue = selectedItem.label || selectedItem.getAttribute('label') || selectedItem.textContent.trim(); - value = selectedItem.getAttribute('value') || selectedItem.value; - value = ( value || value === '') ? value : labelValue; - } + // Value will be either the `value` attribute, or the `value` + // property, or (no choice left) the `labelValue` + value = selectedItem.getAttribute('value'); + if( typeof value === 'undefined' ) value = selectedItem.value; + else if( typeof value === 'undefined' ) value = labelValue; + } this._setValue(value); this._setSelectedItemLabel(labelValue); }, From e559c12d5bae1110c3b73b43a8b9cf9f1d871adc Mon Sep 17 00:00:00 2001 From: Tony Mobily Date: Wed, 21 Sep 2016 12:38:50 +0800 Subject: [PATCH 4/6] Since this is an input element, it should fire 'change' when it's changed --- paper-dropdown-menu.html | 1 + 1 file changed, 1 insertion(+) diff --git a/paper-dropdown-menu.html b/paper-dropdown-menu.html index 022bc31..5d75351 100644 --- a/paper-dropdown-menu.html +++ b/paper-dropdown-menu.html @@ -374,6 +374,7 @@ } this._setValue(value); this._setSelectedItemLabel(labelValue); + this.fire('change'); }, /** From d725f0e996a21dbbf1e853d36e185ec17978d03e Mon Sep 17 00:00:00 2001 From: Tony Mobily Date: Wed, 21 Sep 2016 13:19:25 +0800 Subject: [PATCH 5/6] Fixed that 'if', made sure it's back-compatible with the 'old' way. Tests now pass. --- paper-dropdown-menu.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/paper-dropdown-menu.html b/paper-dropdown-menu.html index 5d75351..940d0e6 100644 --- a/paper-dropdown-menu.html +++ b/paper-dropdown-menu.html @@ -364,13 +364,13 @@ var value = ''; var labelValue = ''; if (selectedItem) { - labelValue = selectedItem.label || selectedItem.getAttribute('label') || selectedItem.textContent.trim(); // Value will be either the `value` attribute, or the `value` // property, or (no choice left) the `labelValue` - value = selectedItem.getAttribute('value'); - if( typeof value === 'undefined' ) value = selectedItem.value; - else if( typeof value === 'undefined' ) value = labelValue; + value = selectedItem.getAttribute('value') || selectedItem.value || selectedItem.label || selectedItem.getAttribute('label') || selectedItem.textContent.trim() + + // Label follows the same rules as above, minus the 'value' prop/att + labelValue = selectedItem.label || selectedItem.getAttribute('label') || selectedItem.textContent.trim(); } this._setValue(value); this._setSelectedItemLabel(labelValue); From 26874e953249bc8c1791eff32738f15766e3da3d Mon Sep 17 00:00:00 2001 From: Tony Mobily Date: Wed, 21 Sep 2016 15:25:20 +0800 Subject: [PATCH 6/6] Changed logic so that '' is considered truly using small wrapping function. Important so that labels and values can be '' --- paper-dropdown-menu.html | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/paper-dropdown-menu.html b/paper-dropdown-menu.html index 940d0e6..18b23d2 100644 --- a/paper-dropdown-menu.html +++ b/paper-dropdown-menu.html @@ -365,12 +365,21 @@ var labelValue = ''; if (selectedItem) { + // It will return a value only if parameter is either truly or '' + // It actually returns an object containing the passed value or null, + // so that chained || will work. + function t( p ){ if( p || p === '' ) return { v: p }; }; + // Value will be either the `value` attribute, or the `value` // property, or (no choice left) the `labelValue` - value = selectedItem.getAttribute('value') || selectedItem.value || selectedItem.label || selectedItem.getAttribute('label') || selectedItem.textContent.trim() + // NOTE: t() is used so that '' is considered truly + value = t( selectedItem.getAttribute('value') ) || t( selectedItem.value ) || t( selectedItem.label) || t( selectedItem.getAttribute('label') ) || t( selectedItem.textContent.trim() ); + value = value.v; // Label follows the same rules as above, minus the 'value' prop/att - labelValue = selectedItem.label || selectedItem.getAttribute('label') || selectedItem.textContent.trim(); + // NOTE: t() is used so that '' is considered truly + labelValue = t( selectedItem.label ) || t( selectedItem.getAttribute('label') ) || t( selectedItem.textContent.trim() ); + labelValue = labelValue.v; } this._setValue(value); this._setSelectedItemLabel(labelValue);