From fddb78a2af23a2a987c711c4a95c6bd7423ac943 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Thu, 19 Oct 2023 09:29:18 +0200 Subject: [PATCH] [IMP] web: SelectMenu: add `autoSort` props By default, the SelectMenu component alphabetically sorts the choices. Before this commit, this wasn't avoidable. As there's now a usecase of SelectMenu where we want to enforce a specific order on the choices (the website AceEditor), this commit introduces a props `autoSort`, which is `true` by default, but which allows to disable the sort. Part-of: odoo/odoo#139154 --- .../src/core/select_menu/select_menu.js | 27 +++++-------------- .../static/tests/core/select_menu_tests.js | 26 +++++++++++++++++- 2 files changed, 32 insertions(+), 21 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 3471a439e2f..7c4435e6907 100644 --- a/addons/web/static/src/core/select_menu/select_menu.js +++ b/addons/web/static/src/core/select_menu/select_menu.js @@ -24,6 +24,7 @@ export class SelectMenu extends Component { onSelect: () => {}, required: false, searchable: true, + autoSort: true, searchPlaceholder: _t("Search..."), choices: [], groups: [], @@ -65,6 +66,7 @@ export class SelectMenu extends Component { togglerClass: { type: String, optional: true }, required: { type: Boolean, optional: true }, searchable: { type: Boolean, optional: true }, + autoSort: { type: Boolean, optional: true }, searchPlaceholder: { type: String, optional: true }, value: { optional: true }, multiSelect: { type: Boolean, optional: true }, @@ -246,9 +248,11 @@ export class SelectMenu extends Component { ); } else { filteredOptions = group.choices; - filteredOptions.sort((optionA, optionB) => - optionA.label.localeCompare(optionB.label) - ); + if (this.props.autoSort) { + filteredOptions.sort((optionA, optionB) => + optionA.label.localeCompare(optionB.label) + ); + } } if (filteredOptions.length === 0) { @@ -264,23 +268,6 @@ export class SelectMenu extends Component { this.sliceDisplayedOptions(); } - /** - * Sorts the choices while keeping the groups separation - * @param {[]} choices - */ - sortGroups(choices) { - const groupsIndex = this.getGroupsIndex(choices); - for (let i = 0; i < groupsIndex.length; i++) { - const startIndex = choices[groupsIndex[i]].isGroup - ? groupsIndex[i] + 1 - : groupsIndex[i]; - const lastIndex = i === groupsIndex.length - 1 ? choices.length : groupsIndex[i + 1]; - const groupSlice = choices.slice(startIndex, lastIndex); - groupSlice.sort((optionA, optionB) => optionA.label.localeCompare(optionB.label)); - choices.splice(startIndex, lastIndex - startIndex, ...groupSlice); - } - } - /** * Returns each group starting index. * @param {[]} choices diff --git a/addons/web/static/tests/core/select_menu_tests.js b/addons/web/static/tests/core/select_menu_tests.js index e1344e90682..acb7fc9ce9a 100644 --- a/addons/web/static/tests/core/select_menu_tests.js +++ b/addons/web/static/tests/core/select_menu_tests.js @@ -315,7 +315,7 @@ QUnit.module("Web Components", (hooks) => { } ); - QUnit.test("Items are sorted based on their label", async (assert) => { + QUnit.test("Items are sorted based on their label by default", async (assert) => { class Parent extends Component { setup() { this.choices = [ @@ -343,6 +343,30 @@ QUnit.module("Web Components", (hooks) => { ); }); + QUnit.test("autoSort props set to false", async (assert) => { + class Parent extends Component { + setup() { + this.choices = [ + { label: "Hello", value: "hello" }, + { label: "World", value: "world" }, + { label: "Foo", value: "foo" }, + { label: "Bar", value: "bar" }, + ]; + } + } + Parent.components = { SelectMenu }; + Parent.template = xml``; + + await mount(Parent, target, { env }); + await open(); + + const choices = [...target.querySelectorAll(".o_select_menu_item_label")]; + assert.deepEqual( + choices.map((el) => el.textContent), + ["Hello", "World", "Foo", "Bar"] + ); + }); + QUnit.test("Custom toggler using default slot", async (assert) => { class Parent extends Component { setup() {