From e8b75e4d99ed8f67b6736c6c1cc4a4ecb7fd53be Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Fri, 21 Apr 2023 09:18:37 +0000 Subject: [PATCH] [FIX] web: multi edit list: crash after validating with ENTER MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Have a multi edit list view, select several records and edit a field represented by an input (e.g. a char field). After typing the new value, press ENTER to validate. The confirmation dialog opens, click on OK/Confirm to save. Before this commit, an error was thrown afterwards, because we tried to retrieve the value from the input, but the input doesn't exist anymore as the edited row has already been switched back to readonly. This commit fixes the issue. closes odoo/odoo#119082 Related: odoo/enterprise#40012 Signed-off-by: Géry Debongnie --- .../src/views/fields/input_field_hook.js | 5 ++- .../web/static/tests/views/list_view_tests.js | 45 +++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/views/fields/input_field_hook.js b/addons/web/static/src/views/fields/input_field_hook.js index 7a081233392..8a4ff114b73 100644 --- a/addons/web/static/src/views/fields/input_field_hook.js +++ b/addons/web/static/src/views/fields/input_field_hook.js @@ -150,9 +150,10 @@ export function useInputField(params) { } if ((val || false) !== (component.props.record.data[component.props.name] || false)) { + const nextValue = inputRef.el.value; await component.props.record.update({ [component.props.name]: val }); - lastSetValue = inputRef.el.value; - component.props.record.model.bus.trigger("FIELD_IS_DIRTY", isDirty); + component.props.record.model.bus.trigger("FIELD_IS_DIRTY", false); + lastSetValue = nextValue; } } } diff --git a/addons/web/static/tests/views/list_view_tests.js b/addons/web/static/tests/views/list_view_tests.js index 2048c72e0e7..e47e7567280 100644 --- a/addons/web/static/tests/views/list_view_tests.js +++ b/addons/web/static/tests/views/list_view_tests.js @@ -14316,6 +14316,51 @@ QUnit.module("Views", (hooks) => { assert.strictEqual(document.activeElement, getDataRow(3).querySelector("[name=foo] input")); }); + QUnit.test("multi-edit records with ENTER does not crash", async (assert) => { + serviceRegistry.add("error", errorService); + + const def = makeDeferred(); + await makeView({ + type: "list", + resModel: "foo", + serverData, + arch: ` + + + + + `, + async mockRPC(route, args) { + if (args.method === "write") { + await def; + } + }, + }); + + await click(getDataRow(2).querySelector(".o_data_row .o_list_record_selector input")); + await click(getDataRow(3).querySelector(".o_data_row .o_list_record_selector input")); + await click(getDataRow(2).querySelector(".o_data_row .o_data_cell[name=int_field]")); + + assert.containsOnce(target, ".o_selected_row"); + const input = getDataRow(2).querySelector("[name=int_field] input"); + assert.strictEqual(document.activeElement, input); + input.value = "234"; + await triggerEvent(input, null, "input"); + triggerHotkey("Enter"); + await triggerEvent(input, null, "change"); + + assert.containsOnce(target, ".o_dialog"); // confirmation dialog + await click(target.querySelector(".o_dialog .modal-footer .btn-primary")); + await new Promise((r) => setTimeout(r, 20)); // delay a bit the save s.t. there's a rendering + def.resolve(); + await nextTick(); + assert.deepEqual( + getNodesTextContent(target.querySelectorAll(".o_data_cell.o_list_number")), + ["10", "234", "234", "-4"] + ); + assert.containsNone(target, ".o_dialog"); // no more confirmation dialog, no error dialog + }); + QUnit.test( "editable grouped list: adding a second record pass the first in readonly", async (assert) => {