[FIX] web: reload Many2XAutocomplete component when updating props

Currently, the Many2XAutocomplete component is not reactive: The component
gets the model to load from its props and the component uses a hook to
initialize and open a SelectCreateDialog dialog for that model. The issue
is that the name of the model is copied and set in the setup function of
the Many2XAutocomplete component. When the model changes, the function
opening the SelectCreateDialog dialog is not updated and will hence still
use the name set initially.

Steps to reproduce the issue:
1. Create a new property field of type Many2one or Many2many
2. Choose a model
3. Click on the "Default Value" field
4. Click on the "Search More..." link from the dropdown
5. Choose another model
6. Click on the "Default Value" field
7. Click on the "Search More..." link from the dropdown
=> The modal displays records from the first model picked.

To fix the issue, we will simply put a `t-key` attribute on the component.
The component will then be reloaded whenever the given key changes. The
model loaded by the SelectCreateDialog dialog will then be updated properly
whenever the given model changes.

task-3192917

closes odoo/odoo#118505

X-original-commit: e9fcc1c950129cdb253df3df2ed7197e3de55fd3
Signed-off-by: Michaël Mattiello <mcm@odoo.com>
Signed-off-by: Banken Julien (jbn) <jbn@odoo.com>
This commit is contained in:
Julien Banken
2023-04-14 10:45:01 +02:00
parent 938c47a76e
commit 9dc4b2b438
2 changed files with 115 additions and 0 deletions
@@ -92,6 +92,7 @@
</t>
<Many2XAutocomplete
t-else=""
t-key="props.id + '_' + props.comodel + '_' + props.string"
value="propertyValue[1] || ''"
id="props.id"
resModel="props.comodel"
@@ -122,6 +123,7 @@
<TagsList tags="propertyValue"/>
<Many2XAutocomplete
t-if="!props.readonly"
t-key="props.id + '_' + props.comodel + '_' + props.string"
id="props.id"
resModel="props.comodel"
autoSelect="true"
@@ -10,7 +10,9 @@ import {
patchWithCleanup,
triggerEvent,
} from "@web/../tests/helpers/utils";
import { Many2XAutocomplete } from "@web/views/fields/relational_utils";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { SelectCreateDialog } from "@web/views/view_dialogs/select_create_dialog";
import { browser } from "@web/core/browser/browser";
import { fieldService } from "@web/core/field_service";
import { registry } from "@web/core/registry";
@@ -1017,6 +1019,117 @@ QUnit.module("Fields", (hooks) => {
);
});
/**
* When the user creates a property field of type many2many, many2one, etc.
* and changes the co-model of the field, the model loaded by the "Search more..."
* modal should correspond to the selected model and should be updated dynamically.
*/
QUnit.test("properties: many2one 'Search more...'", async function (assert) {
async function mockRPC(route, { method, model }) {
if (method === "check_access_rights") {
return true;
} else if (method === "display_name_for" && model === "ir.model") {
return [
{ model: "partner", display_name: "Partner" },
{ model: "res.users", display_name: "User" },
];
} else if (method === "get_available_models" && model === "ir.model") {
return [
{ model: "partner", display_name: "Partner" },
{ model: "res.users", display_name: "User" },
];
}
}
// Patch the test data
serverData.models.partner.records = [
{
id: 1,
company_id: 37,
display_name: "Pierre",
properties: [
{
name: "many_2_one",
type: "many2one",
string: "My Many-2-one",
comodel: "partner",
},
],
},
];
serverData.views = {
"partner,false,list": `
<tree>
<field name="id"/>
<field name="display_name"/>
</tree>`,
"res.users,false,list": `
<tree>
<field name="id"/>
<field name="display_name"/>
</tree>`,
"res.users,false,search": `<search/>`,
};
// Patch the Many2XAutocomplete default search limit options
patchWithCleanup(Many2XAutocomplete.defaultProps, {
searchLimit: -1,
});
// Patch the SelectCreateDialog component
patchWithCleanup(SelectCreateDialog.prototype, {
/**
* @override
*/
setup() {
this._super();
assert.step(this.props.resModel);
},
});
await makeView({
type: "form",
resModel: "partner",
resId: 1,
serverData,
arch: `
<form>
<sheet>
<group>
<field name="company_id" invisible="1"/>
<field name="properties"/>
</group>
</sheet>
</form>`,
mockRPC,
});
// Opening the popover
await click(target, '[property-name="many_2_one"] .o_field_property_open_popover');
const popover = target.querySelector(".o_property_field_popover");
// Opening the "Search more..." modal
await click(popover, ".o_field_property_definition_value input");
await click(popover, ".o_m2o_dropdown_option_search_more");
// Checking the model loaded
assert.verifySteps(["partner"]);
// Closing the modal
await click(target.querySelector(".modal"), ".btn-close");
// Switching the co-model of the property field
await click(popover, ".o_field_property_definition_model input");
await click(popover, ".o_field_property_definition_model .ui-menu-item:nth-child(2)");
// Opening the "Search more..." modal
await click(popover, ".o_field_property_definition_value input");
await click(popover, ".o_m2o_dropdown_option_search_more");
// Checking the model loaded
assert.verifySteps(["res.users"]);
});
QUnit.test("properties: date(time) property manipulations", async function (assert) {
serverData.models.partner.records.push({
id: 5000,