summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js8
-rw-r--r--addons/web/static/tests/fields/relational_fields/field_one2many_tests.js75
2 files changed, 78 insertions, 5 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 649dd3bb1c6..4a3a1930cb1 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -231,7 +231,7 @@ var BasicModel = AbstractModel.extend({
* @returns {Promise} resolved when the fieldInfo have been set on the given
* datapoint and all its children, and all rawChanges have been applied
*/
- addFieldsInfo: function (dataPointID, viewInfo) {
+ addFieldsInfo: async function (dataPointID, viewInfo) {
var dataPoint = this.localData[dataPointID];
dataPoint.fields = _.extend({}, dataPoint.fields, viewInfo.fields);
// complete the given fieldInfo with the fields of the main view, so
@@ -245,7 +245,9 @@ var BasicModel = AbstractModel.extend({
// so we might have stored changes for them (e.g. coming from onchange
// RPCs), that we haven't been able to process earlier (because those
// fields were unknown at that time). So we now try to process them.
- return this.applyRawChanges(dataPointID, viewInfo.viewType).then(() => {
+ if (dataPoint.type === 'record') {
+ await this.applyRawChanges(dataPointID, viewInfo.viewType);
+ }
const proms = [];
const fieldInfo = dataPoint.fieldsInfo[viewInfo.viewType];
// recursively apply the new field info on sub datapoints
@@ -278,8 +280,6 @@ var BasicModel = AbstractModel.extend({
});
}
return Promise.all(proms);
- });
-
},
/**
* Onchange RPCs may return values for fields that are not in the current
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 75346009aaf..f8ff8cba1eb 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
@@ -6511,7 +6511,7 @@ QUnit.module('fields', {}, function () {
form.destroy();
});
- QUnit.test('one2many: onchange that returns unknow field in list, but not in form', async function (assert) {
+ QUnit.test('one2many: onchange that returns unknown field in list, but not in form', async function (assert) {
assert.expect(5);
this.data.partner.onchanges = {
@@ -6563,6 +6563,79 @@ QUnit.module('fields', {}, function () {
form.destroy();
});
+ QUnit.test('multi level of nested x2manys, onchange and rawChanges', async function (assert) {
+ assert.expect(8);
+
+ this.data.partner.records[0].p = [1];
+ this.data.partner.onchanges = {
+ name: function () { },
+ };
+
+ var form = await createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: `
+ <form>
+ <field name="name"/>
+ <field name="p">
+ <tree><field name="display_name"/></tree>
+ <form>
+ <field name="display_name"/>
+ <field name="p">
+ <tree><field name="display_name"/></tree>
+ <form><field name="display_name"/></form>
+ </field>
+ </form>
+ </field>
+ </form>`,
+ mockRPC(route, args) {
+ if (args.method === 'write') {
+ assert.deepEqual(args.args[1].p[0][2], {
+ p: [[1, 1, { display_name: 'new name' }]],
+ });
+ }
+ return this._super(...arguments);
+ },
+ res_id: 1,
+ });
+
+ assert.containsOnce(form, '.o_data_row', "the one2many should contain one row");
+
+ // open the o2m record in readonly first
+ await testUtils.dom.click(form.$('.o_data_row td:first'));
+ assert.containsOnce(document.body, ".modal .o_form_readonly");
+ await testUtils.dom.click($('.modal .modal-footer .o_form_button_cancel'));
+
+ // switch to edit mode and open it again
+ await testUtils.form.clickEdit(form);
+ await testUtils.dom.click(form.$('.o_data_row td:first'));
+
+ assert.containsOnce(document.body, ".modal .o_form_editable");
+ assert.containsOnce(document.body, '.modal .o_data_row', "the one2many should contain one row");
+
+ // open the o2m again, in the dialog
+ await testUtils.dom.click($('.modal .o_data_row td:first'));
+
+ assert.containsN(document.body, ".modal .o_form_editable", 2);
+
+ // edit the name and click save modal that is on top
+ await testUtils.fields.editInput($('.modal:nth(1) .o_field_widget[name=display_name]'), 'new name');
+ await testUtils.dom.click($('.modal:nth(1) .modal-footer .btn-primary'));
+
+ assert.containsOnce(document.body, ".modal .o_form_editable");
+
+ // click save on the other modal
+ await testUtils.dom.click($('.modal .modal-footer .btn-primary'));
+
+ assert.containsNone(document.body, ".modal");
+
+ // save the main record
+ await testUtils.form.clickSave(form);
+
+ form.destroy();
+ });
+
QUnit.test('onchange and required fields with override in arch', async function (assert) {
assert.expect(4);