[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
This commit is contained in:
Aaron Bohy
2023-10-24 12:38:29 +00:00
parent fff1fa0392
commit fddb78a2af
2 changed files with 32 additions and 21 deletions
@@ -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
@@ -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`<SelectMenu choices="choices" autoSort="false"/>`;
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() {