diff --git a/addons/web/static/src/js/views/form/form_controller.js b/addons/web/static/src/js/views/form/form_controller.js index fa84f11df7f..7ddd3d16587 100644 --- a/addons/web/static/src/js/views/form/form_controller.js +++ b/addons/web/static/src/js/views/form/form_controller.js @@ -217,7 +217,7 @@ var FormController = BasicController.extend({ * * @private * @override method from field manager mixin - * @param {string} id + * @param {string} id - id of the previously changed record * @returns {Deferred} */ _confirmSave: function (id) { @@ -228,15 +228,21 @@ var FormController = BasicController.extend({ return this._setMode('readonly'); } } else { - // a subrecord changed, so update the corresponding relational field + // A subrecord has changed, so update the corresponding relational field // i.e. the one whose value is a record with the given id or a list // having a record with the given id in its data var record = this.model.get(this.handle); - var fieldsChanged = _.findKey(record.data, function (d) { - return _.isObject(d) && - (d.id === id || _.findWhere(d.data, {id: id})); - }); - return this.renderer.confirmChange(record, record.id, [fieldsChanged]); + + // Callback function which returns true + // if a value recursively contains a record with the given id. + // This will be used to determine the list of fields to reload. + var containsChangedRecord = function (value) { + return _.isObject(value) && + (value.id === id || _.find(value.data, containsChangedRecord)); + }; + + var changedFields = _.findKey(record.data, containsChangedRecord); + return this.renderer.confirmChange(record, record.id, [changedFields]); } }, /** diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index 0ad9aa2a416..f9b6e9dfaeb 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -1418,6 +1418,58 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('updating a many2one from a many2many', function (assert) { + assert.expect(4); + + this.data.turtle.records[1].turtle_trululu = 1; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
', + res_id: 1, + archs: { + 'partner,false,form': '', + }, + mockRPC: function (route, args) { + if (args.method === 'get_formview_id') { + assert.deepEqual(args.args[0], [1], "should call get_formview_id with correct id"); + return $.when(false); + } + return this._super(route, args); + }, + }); + + // Opening the modal + form.$buttons.find('.o_form_button_edit').click(); + form.$('.o_data_row td:contains(first record)').click(); + form.$('.o_external_button').click(); + assert.strictEqual($('.modal').length, 1, + "should have one modal in body"); + + // Changing the 'trululu' value + $('.modal input[name="display_name"]').val('test').trigger('input'); + $('.modal button.btn-primary').click(); + + // Test whether the value has changed + assert.strictEqual($('.modal').length, 0, + "the modal should be closed"); + assert.equal(form.$('.o_data_cell:contains(test)').text(), 'test', + "the partner name should have been updated to 'test'"); + + form.destroy(); + }); + QUnit.module('FieldOne2Many'); QUnit.test('one2many basic properties', function (assert) {