From 8a4485748f49c5b8fdb780b0bcd2435eeadd63bf Mon Sep 17 00:00:00 2001 From: luvi Date: Fri, 7 Jul 2023 06:26:01 +0000 Subject: [PATCH] [FIX] web: fix filtering when choices/groups props update This commit fixes the filtering of choices when the choices or the groups props values are updated. Before this commit, the filter was only triggered when the length of choices or groups differ. Instead, it is prefered to apply the filter of choices whenever those props are updated (in a dedicated useEffect). A test has been added, updating the choices props, while having an object with the same number of choices, while having different values. Before this fix, the filtering wouldn't be applied correctly, since the filter wouldn't be triggered because the object has the same number of values in it. closes odoo/odoo#127733 Signed-off-by: Bastien Fafchamps (bafa) --- .../src/core/select_menu/select_menu.js | 16 ++--- .../static/tests/core/select_menu_tests.js | 61 +++++++++++++++++++ 2 files changed, 69 insertions(+), 8 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 7312c264247..e549c8a4059 100644 --- a/addons/web/static/src/core/select_menu/select_menu.js +++ b/addons/web/static/src/core/select_menu/select_menu.js @@ -1,6 +1,6 @@ /** @odoo-module **/ -import { Component, useState, useRef, onWillUpdateProps } from "@odoo/owl"; +import { Component, useState, useRef, onWillUpdateProps, useEffect } from "@odoo/owl"; import { Dropdown } from "@web/core/dropdown/dropdown"; import { DropdownItem } from "@web/core/dropdown/dropdown_item"; import { _lt } from "@web/core/l10n/translation"; @@ -94,14 +94,14 @@ export class SelectMenu extends Component { if (this.props.value !== nextProps.value) { this.selectedChoice = this.getSelectedChoice(nextProps); } - if ( - this.props.choices.length !== nextProps.choices.length || - this.props.groups.length !== nextProps.groups.length - ) { - const groups = [{ choices: nextProps.choices }, ...nextProps.groups]; - this.filterOptions(this.state.searchValue, groups); - } }); + useEffect( + () => { + const groups = [{ choices: this.props.choices }, ...this.props.groups]; + this.filterOptions(this.state.searchValue, groups); + }, + () => [this.props.choices, this.props.groups] + ); } get displayValue() { diff --git a/addons/web/static/tests/core/select_menu_tests.js b/addons/web/static/tests/core/select_menu_tests.js index 275c5b61124..e1344e90682 100644 --- a/addons/web/static/tests/core/select_menu_tests.js +++ b/addons/web/static/tests/core/select_menu_tests.js @@ -912,6 +912,7 @@ QUnit.module("Web Components", (hooks) => { ); await editInput(target, "input.o_select_menu_sticky", "cou"); + await nextTick(); assert.strictEqual( target.querySelector(".o_select_menu_menu").textContent, "Coucou", @@ -929,4 +930,64 @@ QUnit.module("Web Components", (hooks) => { "SelectMenu has two choices available" ); }); + + QUnit.test("Choices are updated and filtered when props change", async (assert) => { + class Parent extends Component { + setup() { + this.state = useState({ + choices: [ + { label: "Hello", value: "hello" }, + { label: "Coucou", value: "hello2" }, + ], + value: "hello", + }); + } + + onInput() { + this.state.choices = [ + { label: "Coucou", value: "hello2" }, + { label: "Good afternoon", value: "hello3" }, + ]; + } + + onSelect(value) { + assert.step(value); + this.state.value = value; + } + } + Parent.components = { SelectMenu }; + Parent.template = xml` + + `; + + await mount(Parent, target, { env }); + assert.strictEqual(getValue(), "Hello"); + + await open(); + assert.strictEqual( + target.querySelector(".o_select_menu_menu").textContent, + "CoucouHello", + "SelectMenu has two choices available" + ); + + // edit the input, to trigger onInput and update the props + await editInput(target, "input.o_select_menu_sticky", "aft"); + await nextTick(); + + await click(target.querySelectorAll(".o_select_menu_item_label")[0]); + assert.verifySteps(["hello3"], "added item can be selected"); + assert.strictEqual(getValue(), "Good afternoon"); + + await open(); + assert.strictEqual( + target.querySelector(".o_select_menu_menu").textContent, + "CoucouGood afternoon", + "SelectMenu has two updated choices available" + ); + }); });