diff --git a/addons/web/static/src/js/views/form_view.js b/addons/web/static/src/js/views/form_view.js index 0330c5d95cb..640644b482a 100644 --- a/addons/web/static/src/js/views/form_view.js +++ b/addons/web/static/src/js/views/form_view.js @@ -55,7 +55,6 @@ var FormView = View.extend(common.FieldManagerMixin, { this.fields = {}; this.fields_order = []; this.datarecord = {}; - this._onchange_specs = {}; this.onchanges_mutex = new utils.Mutex(); this.default_focus_field = null; this.default_focus_button = null; @@ -75,7 +74,6 @@ var FormView = View.extend(common.FieldManagerMixin, { this.rendering_engine = new FormRenderingEngine(this); this.set({actual_mode: this.options.initial_mode}); this.has_been_loaded.done(function() { - self._build_onchange_specs(); self.on("change:actual_mode", self, self.toggle_buttons); self.on("change:actual_mode", self, self.toggle_sidebar); }); @@ -318,8 +316,11 @@ var FormView = View.extend(common.FieldManagerMixin, { this.update_pager(); // the mode must be actualized before updating the pager return $.when.apply(null, set_values).then(function() { if (!record.id) { - // trigger onchanges - self.do_onchange(null); + // trigger onchange for new record after x2many with non-embedded views are loaded + var fields_loaded = _.pluck(self.fields, 'is_loaded'); + $.when.apply(null, fields_loaded).done(function() { + self.do_onchange(null); + }); } self.on_form_changed(); self.rendering_engine.init_fields().then(function() { @@ -333,7 +334,7 @@ var FormView = View.extend(common.FieldManagerMixin, { } else { self.do_push_state({}); } - self.$el.removeClass('oe_form_dirty'); + self.$el.removeClass('oe_form_dirty'); }); }); }, @@ -381,7 +382,24 @@ var FormView = View.extend(common.FieldManagerMixin, { _.each(this.fields, function(field, name) { self._onchange_fields.push(name); self._onchange_specs[name] = find(name, field.node); - _.each(field.field.views, function(view) { + + // we get the list of first-level fields of x2many firstly by + // getting them from the field embedded views, then if no embedded + // view is present for a loaded view, we get them from the default + // view that has been loaded + + // gather embedded view objects + var views = _.clone(field.field.views); + // also gather default view objects + if (field.viewmanager) { + _.each(field.viewmanager.views, function(view, view_type) { + // add default view if it was not embedded and it is loaded + if (views[view_type] === undefined && view.controller) { + views[view_type] = view.controller.fields_view; + } + }); + } + _.each(views, function(view) { _.each(view.fields, function(_, subname) { self._onchange_specs[name + '.' + subname] = find(subname, view.arch); }); @@ -410,6 +428,9 @@ var FormView = View.extend(common.FieldManagerMixin, { do_onchange: function(widget) { var self = this; + if (self._onchange_specs === undefined) { + self._build_onchange_specs(); + } var onchange_specs = self._onchange_specs; try { var def = $.when({}); diff --git a/odoo/addons/test_new_api/tests/test_onchange.py b/odoo/addons/test_new_api/tests/test_onchange.py index 0301ca2b3e4..a6e2bff1b35 100644 --- a/odoo/addons/test_new_api/tests/test_onchange.py +++ b/odoo/addons/test_new_api/tests/test_onchange.py @@ -307,12 +307,7 @@ class TestOnChange(common.TransactionCase): # When one2many domain contains non-computed field, things are ok self.assertEqual(result['value']['important_messages'], - [(5,)] + [(1, msg.id, { - 'name': msg.name, - 'body': msg.body, - 'author': (msg.author.id, msg.author.display_name), - 'size': msg.size - }) for msg in discussion.important_messages]) + [(5,)] + [(4, msg.id) for msg in discussion.important_messages]) # But here with commit 5676d81, we get value of: [(2, email.id)] self.assertEqual( diff --git a/odoo/fields.py b/odoo/fields.py index c004b640cd2..2f898221e99 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -2133,7 +2133,7 @@ class One2many(_RelationalMulti): _description_relation_field = property(attrgetter('inverse_name')) def convert_to_onchange(self, value, record, fnames=()): - fnames = set(fnames or value.fields_view_get()['fields']) + fnames = set(fnames or ()) fnames.discard(self.inverse_name) return super(One2many, self).convert_to_onchange(value, record, fnames)