From 22f31a5d0c97901e9b123d467c82322c824c25d0 Mon Sep 17 00:00:00 2001 From: FrancoisGe Date: Mon, 2 Oct 2023 09:04:57 +0200 Subject: [PATCH] [FIX] web: external button in many2one field The goal of this commit is to fix two problems in the Many2one field: 1. At setup, the field is considered to be isFloating when its value is false. 2. When "xxx" is encoded and "Create xxx" is selected, the field is still considered to be isFloating even the selection. isFloating should only be true when the user is performing a search, when they have made their choice isFloating should be set to false. These problems should result in the external button not being displayed in these two cases. Currently, the button is displayed correctly due to a bug in owl. The bug in owl causes all Components that have executed evaluateExpr with record.evalContext will be render each time record.update is called. For example, for Many2oneField, it is the call to dynamic.context in extractProps that will cause the rendering of the Component Field containing Many2oneField. This will trigger a call to onWillUpdateProps each time record.update is called, and will modify isFloating to make it correct. In order to fix OWL without introducing any bugs, we're going to fix these problems. How to reproduce after OWL is fixed: ==================================== Case 1: ------ - Go to a form view with an field "x" (with an onchange) and a many2one field - Create a new record (the many2one field is empty) - Edit field "x" - The onChange returns a value for the many2one Before this commit: The external button is not displayed After this commit The external button is displayed. Case 2: ------ - Go to a form view with a many2one field - Insert "blabla" in the many2one - Click on "Create blabla". Before this commit: The external button is not displayed After this commit The external button is displayed. closes odoo/odoo#137212 Signed-off-by: Aaron Bohy (aab) --- .../views/fields/many2one/many2one_field.js | 5 ++-- .../views/fields/many2one_field_tests.js | 30 ++++++++++++++++++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/addons/web/static/src/views/fields/many2one/many2one_field.js b/addons/web/static/src/views/fields/many2one/many2one_field.js index 61c8b6ec3b9..998256657dc 100644 --- a/addons/web/static/src/views/fields/many2one/many2one_field.js +++ b/addons/web/static/src/views/fields/many2one/many2one_field.js @@ -104,7 +104,7 @@ export class Many2OneField extends Component { }; this.state = useState({ - isFloating: !this.value, + isFloating: false, }); this.computeActiveActions(this.props); @@ -137,6 +137,7 @@ export class Many2OneField extends Component { if (params.triggeredOnBlur) { return this.openConfirmationDialog(name); } + this.state.isFloating = false; return this.updateRecord([false, name]); }; } @@ -146,8 +147,6 @@ export class Many2OneField extends Component { }; onWillUpdateProps(async (nextProps) => { - this.state.isFloating = - "value" in nextProps ? !nextProps.value : !nextProps.record.data[nextProps.name]; this.computeActiveActions(nextProps); }); } diff --git a/addons/web/static/tests/views/fields/many2one_field_tests.js b/addons/web/static/tests/views/fields/many2one_field_tests.js index 2c09edbca4e..bf7d1cd6002 100644 --- a/addons/web/static/tests/views/fields/many2one_field_tests.js +++ b/addons/web/static/tests/views/fields/many2one_field_tests.js @@ -741,7 +741,7 @@ QUnit.module("Fields", (hooks) => { const input = target.querySelector(".o_field_widget[name=user_id] input"); await editInput(input, null, "yy"); await clickOpenedDropdownItem(target, "user_id", 'Create "yy"'); - + assert.containsOnce(target, ".o_external_button"); assert.verifySteps(["name_create"]); } ); @@ -4487,4 +4487,32 @@ QUnit.module("Fields", (hooks) => { "aaa" ); }); + + QUnit.test( + "external button must be displayed after the update caused by an onchange", + async function (assert) { + serverData.models.partner.onchanges = { + display_name: function (obj) { + if (obj.display_name) { + obj.trululu = 1; + } + }, + }; + await makeView({ + type: "form", + resModel: "partner", + serverData, + arch: ` +
+ + + `, + }); + + assert.containsNone(target, ".o_external_button"); + + await editInput(target, "[name=display_name] input", "new value"); + assert.containsOnce(target, ".o_external_button"); + } + ); });