diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index e5f20378dea..3063e56d0b1 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -3369,6 +3369,21 @@ var BasicModel = AbstractModel.extend({ } } else { // the subrecord is new, so create it + + // we may have received values from an onchange for fields that are + // not in the view, and that we don't even know, as we don't have the + // fields_get of models of related fields. We save those values + // anyway, but for many2ones, we have to extract the id from the pair + // [id, display_name] + const rawChangesEntries = Object.entries(relRecord._rawChanges); + for (const [fieldName, value] of rawChangesEntries) { + const isMany2OneValue = Array.isArray(value) && + value.length === 2 && + Number.isInteger(value[0]) && + typeof value[1] === 'string'; + changes[fieldName] = isMany2OneValue ? value[0] : value; + } + commands[fieldName].push(x2ManyCommands.create(relRecord.ref, changes)); } } diff --git a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js index 3ae0c69bfda..e24341b1019 100644 --- a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js +++ b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js @@ -9161,6 +9161,53 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + + QUnit.test('one2many value returned by onchange with unknown fields', async function (assert) { + assert.expect(3); + + this.data.partner.onchanges = { + bar: function (obj) { + obj.p = [ + [5], + [0, 0, { + bar: true, + display_name: "coucou", + trululu: [2, 'second record'], + turtles: [[5], [0, 0, {turtle_int: 4}]], + }] + ]; + }, + }; + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: ` +
`, + mockRPC(route, args) { + if (args.method === 'create') { + assert.deepEqual(args.args[0].p[0][2], { + bar: true, + display_name: "coucou", + trululu: 2, + turtles: [[5], [0, 0, {turtle_int: 4}]], + }); + } + return this._super(...arguments); + }, + }); + + assert.containsOnce(form, '.o_field_many2manytags .badge'); + assert.strictEqual(form.$('.o_field_many2manytags .o_badge_text').text(), 'coucou'); + + await testUtils.form.clickSave(form); + + form.destroy(); + }); }); }); });