From 66289abd5ebf508b073864a1f643eb862cf4b065 Mon Sep 17 00:00:00 2001 From: "Simon Genin (ges)" Date: Mon, 19 Sep 2022 12:35:09 +0000 Subject: [PATCH] [FIX] web: fix reactivity in custom filter menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before: On a map view, a bunch of points get loaded one by one. Each of them triggering a new render of the controller. Currently, the useModel hook does a deep render no matter what. If you are trying to set a custom filter un the filter menu in the control panel, the content would systematically diseapear (rerendered) when a new map point loaded. After: To prevent this, setting the input node as t-model is a solution. It allows owl to keep track of the value of the input and correctly set it back when a render occurs. closes odoo/odoo#100421 Signed-off-by: Géry Debongnie --- .../search/filter_menu/custom_filter_item.xml | 6 ++--- .../tests/search/custom_filter_item_tests.js | 26 +++++++++++++++++++ addons/web/static/tests/search/helpers.js | 8 ++++-- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/addons/web/static/src/search/filter_menu/custom_filter_item.xml b/addons/web/static/src/search/filter_menu/custom_filter_item.xml index dbfc1b118bb..74917d2622b 100644 --- a/addons/web/static/src/search/filter_menu/custom_filter_item.xml +++ b/addons/web/static/src/search/filter_menu/custom_filter_item.xml @@ -65,20 +65,20 @@ t-att-type="DECIMAL_POINT === '.' ? 'number' : 'text'" t-attf-title="Number using {{ DECIMAL_POINT }} as decimal separator." t-attf-pattern="[0-9]+([\\{{ DECIMAL_POINT }}][0-9]+)?" - t-att-value="condition.displayedValue" + t-model="condition.displayedValue" t-on-change="ev => this.onValueChange(condition, ev)" /> diff --git a/addons/web/static/tests/search/custom_filter_item_tests.js b/addons/web/static/tests/search/custom_filter_item_tests.js index 43fe2230408..0eb62991aa1 100644 --- a/addons/web/static/tests/search/custom_filter_item_tests.js +++ b/addons/web/static/tests/search/custom_filter_item_tests.js @@ -3,6 +3,7 @@ import { click, getFixture, + nextTick, patchDate, patchTimeZone, patchWithCleanup, @@ -743,4 +744,29 @@ QUnit.module("Search", (hooks) => { "The delete button is shown as a trash icon" ); }); + + QUnit.test("condition value is not lost on deep render", async function (assert) { + const component = await makeWithSearch({ + serverData, + resModel: "foo", + Component: ControlPanel, + searchViewId: false, + searchMenuTypes: ["filter"], + }); + + await toggleFilterMenu(target); + await toggleAddCustomFilter(target); + + await editConditionField(target, 0, "char_field"); + await editConditionValue(target, 0, "Coucou", 0, false); + + let charInput = target.querySelector(".o_generator_menu_value .o_input"); + assert.strictEqual(charInput.value, "Coucou"); + + component.render(true); + await nextTick(); + + charInput = target.querySelector(".o_generator_menu_value .o_input"); + assert.strictEqual(charInput.value, "Coucou"); + }); }); diff --git a/addons/web/static/tests/search/helpers.js b/addons/web/static/tests/search/helpers.js index 3c282ef9040..01f4b6f5d19 100644 --- a/addons/web/static/tests/search/helpers.js +++ b/addons/web/static/tests/search/helpers.js @@ -7,6 +7,7 @@ import { getFixture, mount, mouseEnter, + nextTick, triggerEvent, } from "@web/../tests/helpers/utils"; import { hotkeyService } from "@web/core/hotkeys/hotkey_service"; @@ -175,7 +176,7 @@ export async function editConditionOperator(el, index, operator) { await triggerEvent(select, null, "change"); } -export async function editConditionValue(el, index, value, valueIndex = 0) { +export async function editConditionValue(el, index, value, valueIndex = 0, triggerChange = true) { const condition = findItem(el, `.o_filter_condition`, index); const target = findItem( condition, @@ -183,7 +184,10 @@ export async function editConditionValue(el, index, value, valueIndex = 0) { valueIndex ); target.value = value; - await triggerEvent(target, null, "change"); + if (triggerChange) { + triggerEvent(target, null, "change"); + } + await nextTick(); } export async function applyFilter(el) {