diff --git a/addons/mail/static/src/js/form_renderer.js b/addons/mail/static/src/js/form_renderer.js index 4d07168e501..520827d7695 100644 --- a/addons/mail/static/src/js/form_renderer.js +++ b/addons/mail/static/src/js/form_renderer.js @@ -70,6 +70,22 @@ FormRenderer.include({ return this._super.apply(this, arguments); } }, + /** + * Detaches the chatter before updating the $el. This is important because + * if the view is now in create mode (edit mode with no res_id), the chatter + * will be removed from the DOM, and its handlers will be unbound. By + * detaching it beforehand, we ensure to keep its handlers alive so that if + * it is re-appended later, everything will still work properly. + * + * @override + * @private + */ + _updateView: function () { + if (this.chatter) { + this.chatter.$el.detach(); + } + return this._super.apply(this, arguments); + }, }); }); diff --git a/addons/mail/static/tests/chatter_tests.js b/addons/mail/static/tests/chatter_tests.js index ea8c00991e3..b20733949e2 100644 --- a/addons/mail/static/tests/chatter_tests.js +++ b/addons/mail/static/tests/chatter_tests.js @@ -155,7 +155,7 @@ QUnit.test('basic rendering', function (assert) { }); QUnit.test('chatter is not rendered in mode === create', function (assert) { - assert.expect(2); + assert.expect(4); var form = createView({ View: FormView, @@ -171,11 +171,8 @@ QUnit.test('chatter is not rendered in mode === create', function (assert) { '', res_id: 2, mockRPC: function (route, args) { - if (route === '/mail/read_followers') { - return $.when({ - followers: [], - subtypes: [], - }); + if (route === "/web/dataset/call_kw/partner/message_get_suggested_recipients") { + return $.when({2: []}); } return this._super(route, args); }, @@ -191,9 +188,25 @@ QUnit.test('chatter is not rendered in mode === create', function (assert) { }, }); - assert.ok(form.$('.o_chatter').length, "there should be a chatter widget"); + assert.strictEqual(form.$('.o_chatter').length, 1, + "chatter should be displayed"); + form.$buttons.find('.o_form_button_create').click(); - assert.ok(!form.$('.o_chatter').length, "there should not be a chatter widget"); + + assert.strictEqual(form.$('.o_chatter').length, 0, + "chatter should not be displayed"); + + form.$('.o_form_input').val('coucou').trigger('input'); + form.$buttons.find('.o_form_button_save').click(); + + assert.strictEqual(form.$('.o_chatter').length, 1, + "chatter should be displayed"); + + // check if chatter buttons still work + form.$('.o_chatter_button_new_message').click(); + assert.strictEqual(form.$('.o_chat_composer:visible').length, 1, + "chatter should be opened"); + form.destroy(); }); diff --git a/addons/web/static/src/js/views/form/form_renderer.js b/addons/web/static/src/js/views/form/form_renderer.js index 53d5a49b68c..6955ca47c5c 100644 --- a/addons/web/static/src/js/views/form/form_renderer.js +++ b/addons/web/static/src/js/views/form/form_renderer.js @@ -692,31 +692,44 @@ var FormRenderer = BasicRenderer.extend({ delete this.defs; return $.when.apply($, defs).then(function () { - self.$el.html($form.contents()); + self._updateView($form.contents()); + }); + }, + /** + * Updates the form's $el with new content. + * + * @private + * @see _renderView + * @param {JQuery} $newContent + */ + _updateView: function ($newContent) { + var self = this; - // Necessary to allow all sub widgets to use their dimensions in - // layout related activities, such as autoresize on fieldtexts - core.bus.trigger('DOM_updated'); + // Set the new content of the form view, and toggle classnames + this.$el.html($newContent); + this.$el.toggleClass('o_form_nosheet', !this.has_sheet); + this.$el.toggleClass('o_form_editable', this.mode === 'edit'); + this.$el.toggleClass('o_form_readonly', this.mode === 'readonly'); - self.$el.toggleClass('o_form_nosheet', !self.has_sheet); - self.$el.toggleClass('o_form_editable', self.mode === 'edit'); - self.$el.toggleClass('o_form_readonly', self.mode === 'readonly'); - // Attach the tooltips on the fields' label - var focusWidget = self.defaultFocusField; - _.each(self.allFieldWidgets[self.state.id], function (widget) { - if (!focusWidget) { - focusWidget = widget; - } - if (core.debug || widget.attrs.help || widget.field.help) { - var idForLabel = self.idsForLabels[widget.name]; - var $label = idForLabel ? self.$('label[for=' + idForLabel + ']') : $(); - self._addFieldTooltip(widget, $label); - } - }); - if (focusWidget) { - focusWidget.activate(true); + // Necessary to allow all sub widgets to use their dimensions in + // layout related activities, such as autoresize on fieldtexts + core.bus.trigger('DOM_updated'); + + // Attach the tooltips on the fields' label + var focusWidget = this.defaultFocusField; + _.each(this.allFieldWidgets[this.state.id], function (widget) { + if (!focusWidget) { + focusWidget = widget; + } + if (core.debug || widget.attrs.help || widget.field.help) { + var idForLabel = self.idsForLabels[widget.name]; + var $label = idForLabel ? self.$('label[for=' + idForLabel + ']') : $(); + self._addFieldTooltip(widget, $label); } }); + if (focusWidget) { + focusWidget.activate(true); + } }, //--------------------------------------------------------------------------