From ff019aa52f4857b45ebad301757970d99df37aee Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Thu, 15 Feb 2018 10:14:15 +0100 Subject: [PATCH] [FIX] web: BasicModel: onchange on X2M: handle command 6 Before this rev., when an onchange returned a command 6 for an x2many field, it was completely ignored by the BasicModel. --- .../static/src/js/views/basic/basic_model.js | 38 +++++++++++------- .../tests/fields/relational_fields_tests.js | 39 +++++++++++++++++++ 2 files changed, 64 insertions(+), 13 deletions(-) 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 ff4ed6d9147..6eef41f149d 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -1452,22 +1452,15 @@ var BasicModel = AbstractModel.extend({ defs.push(self._applyOnChange(command[2], rec)); } else if (command[0] === 4) { // LINK TO - rec = self.localData[list._cache[command[1]]]; - if (rec) { - // modifications done on a record are discarded if - // the onchange uses a LINK TO - self.discardChanges(rec.id); - } - // the dataPoint id will be set when the record will be - // fetched (for now, this dataPoint may not exist yet) - list._changes.push({ - operation: 'ADD', - id: rec ? rec.id : null, - resID: command[1], - }); + linkRecord(list, command[1]); } else if (command[0] === 5) { // DELETE ALL list._changes = [{operation: 'REMOVE_ALL'}]; + } else if (command[0] === 6) { + list._changes = [{operation: 'REMOVE_ALL'}]; + _.each(command[2], function (resID) { + linkRecord(list, resID); + }); } }); var def = self._readUngroupedList(list).then(function () { @@ -1484,6 +1477,25 @@ var BasicModel = AbstractModel.extend({ } }); return $.when.apply($, defs); + + // inner function that adds a record (based on its res_id) to a list + // dataPoint (used for onchanges that return commands 4 (LINK TO) or + // commands 6 (REPLACE WITH)) + function linkRecord (list, resID) { + rec = self.localData[list._cache[resID]]; + if (rec) { + // modifications done on a record are discarded if the onchange + // uses a LINK TO or a REPLACE WITH + self.discardChanges(rec.id); + } + // the dataPoint id will be set when the record will be fetched (for + // now, this dataPoint may not exist yet) + list._changes.push({ + operation: 'ADD', + id: rec ? rec.id : null, + resID: resID, + }); + } }, /** * When an operation is applied to a x2many field, the field widgets diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index e928d4b9f2c..4f7041ad2d5 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -2906,6 +2906,45 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('onchange returning a command 6 for an x2many', function (assert) { + assert.expect(2); + + this.data.partner.onchanges = { + foo: function (obj) { + obj.turtles = [[6, false, [1, 2, 3]]]; + }, + }; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch:'
' + + '' + + '' + + '' + + '' + + '' + + '' + + '', + res_id: 1, + viewOptions: { + mode: 'edit', + }, + }); + + assert.strictEqual(form.$('.o_data_row').length, 1, + "there should be one record in the relation"); + + // change the value of foo to trigger the onchange + form.$('.o_field_widget[name=foo]').val('some value').trigger('input'); + + assert.strictEqual(form.$('.o_data_row').length, 3, + "there should be three records in the relation"); + + form.destroy(); + }); + QUnit.test('x2many fields inside x2manys are fetched after an onchange', function (assert) { assert.expect(6);