From 69d7baa7af485a284c4c6a1daaaba17d855ed37b Mon Sep 17 00:00:00 2001 From: luvi Date: Thu, 25 Jan 2024 14:15:18 +0100 Subject: [PATCH] [FIX] web: show label for null and empty strings value in SelectMenu This commit fixes the behavior of the SelectMenu component when an option is being used with an empty string or a null value. Let's suppose we have the following choices: { label: 'Empty', value: '' }, { label: 'Full', value: 'full' } Before this fix, when selecting 'Empty', the value would be selected in the menu, but the toggler would still be empty, as if no value was selected. Now, any value corresponding to a choice value can be selected. A test has been added for each value supported (null and empty strings). Part-of: odoo/odoo#151276 --- .../src/core/select_menu/select_menu.js | 14 +-- .../static/tests/core/select_menu_tests.js | 87 +++++++++++++++++++ 2 files changed, 90 insertions(+), 11 deletions(-) diff --git a/addons/web/static/src/core/select_menu/select_menu.js b/addons/web/static/src/core/select_menu/select_menu.js index 7c4435e6907..925530922c5 100644 --- a/addons/web/static/src/core/select_menu/select_menu.js +++ b/addons/web/static/src/core/select_menu/select_menu.js @@ -114,11 +114,7 @@ export class SelectMenu extends Component { } get canDeselect() { - return ( - !this.props.required && - this.selectedChoice !== undefined && - this.selectedChoice !== null - ); + return !this.props.required && this.selectedChoice !== undefined; } get multiSelectChoices() { @@ -197,12 +193,8 @@ export class SelectMenu extends Component { } getSelectedChoice(props) { - if (props.value) { - const choices = [...props.choices, ...props.groups.flatMap((g) => g.choices)]; - return choices.find((c) => c.value === props.value); - } else { - return undefined; - } + const choices = [...props.choices, ...props.groups.flatMap((g) => g.choices)]; + return choices.find((c) => c.value === props.value); } onItemSelected(value) { diff --git a/addons/web/static/tests/core/select_menu_tests.js b/addons/web/static/tests/core/select_menu_tests.js index acb7fc9ce9a..920f1868d05 100644 --- a/addons/web/static/tests/core/select_menu_tests.js +++ b/addons/web/static/tests/core/select_menu_tests.js @@ -237,6 +237,93 @@ QUnit.module("Web Components", (hooks) => { ); }); + QUnit.test("Use a null value for choices", async (assert) => { + class Parent extends Component { + static components = { SelectMenu }; + static template = xml` + + `; + setup() { + this.choices = [ + { label: "Nothing", value: null }, + { label: "Everything", value: "things" }, + ]; + this.state = useState({ + value: null, + }); + } + setValue(newValue) { + this.state.value = newValue; + } + } + + const comp = await mount(Parent, target, { env }); + assert.equal( + getValue(), + "Nothing", + `The select value with an empty string has the "Null" value selected` + ); + + comp.setValue("things"); + await nextTick(); + assert.equal( + getValue(), + "Everything", + `After changing the value props, the select value shoud be "Everything"` + ); + }); + + QUnit.test( + "Use an empty string as the value for a choice display the corresponding choice", + async (assert) => { + class Parent extends Component { + static components = { SelectMenu }; + static template = xml` + + `; + setup() { + this.choices = [ + { label: "Empty", value: "" }, + { label: "Full", value: "full" }, + ]; + this.state = useState({ value: "" }); + } + setValue(newValue) { + this.state.value = newValue; + } + } + + const comp = await mount(Parent, target, { env }); + assert.equal( + getValue(), + "Empty", + `The select value with an empty string has the "Empty" value selected` + ); + + comp.setValue("full"); + await nextTick(); + assert.equal( + getValue(), + "Full", + `After changing the value props, the select value shoud be "Full"` + ); + + comp.setValue(null); + await nextTick(); + assert.equal( + getValue(), + "", + `After changing the value props to a null value, the select has no value selected` + ); + } + ); + QUnit.test( "Clear button calls 'onSelect' with null value and appears only when value is not null", async (assert) => {