diff --git a/addons/web/static/src/js/views/basic/basic_controller.js b/addons/web/static/src/js/views/basic/basic_controller.js index 24b5c7fa3d0..2847003f5df 100644 --- a/addons/web/static/src/js/views/basic/basic_controller.js +++ b/addons/web/static/src/js/views/basic/basic_controller.js @@ -33,6 +33,7 @@ return AbstractController.extend(FieldManagerMixin, { this.hasButtons = params.hasButtons; FieldManagerMixin.init.call(this, this.model); this.handle = params.initialState.id; + this.isDirty = false; }, /** * @override @@ -148,6 +149,18 @@ return AbstractController.extend(FieldManagerMixin, { // Handlers //-------------------------------------------------------------------------- + /** + * We need to keep manually track of the isDirty property. Note that it is + * not the same as the one from the basic model. A new record from the + * basic model is considered dirty, but from the controller point of view, + * there was no user interaction and should not be dirty. + * + * @private + */ + _onFieldChanged: function () { + this.isDirty = true; + FieldManagerMixin._onFieldChanged.apply(this, arguments); + }, /** * When a reload event triggers up, we need to reload the full view. * For example, after a form view dialog saved some data. 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 8a630e30905..1493297ae97 100644 --- a/addons/web/static/src/js/views/form/form_controller.js +++ b/addons/web/static/src/js/views/form/form_controller.js @@ -267,7 +267,7 @@ var FormController = BasicController.extend({ * can be discarded. If it has been rejected, then we cannot discard. */ _canBeDiscarded: function () { - if (!this.model.isDirty(this.handle)) { + if (!this.isDirty) { return $.when(); } var message = _t("The record has been modified, your changes will be discarded. Are you sure you want to leave this page ?"); @@ -452,6 +452,7 @@ var FormController = BasicController.extend({ var self = this; this.model.duplicateRecord(this.handle) .then(function (handle) { + self.isDirty = false; self.handle = handle; self._updateEnv(); self._toEditMode(); diff --git a/addons/web/static/test/views/form_tests.js b/addons/web/static/test/views/form_tests.js index 4f80c5e50b9..1295282732c 100644 --- a/addons/web/static/test/views/form_tests.js +++ b/addons/web/static/test/views/form_tests.js @@ -1228,6 +1228,58 @@ QUnit.module('Views', { form.destroy(); }); + QUnit.test('discard changes on a new (non dirty, except for defaults) form view', function (assert) { + assert.expect(2); + + this.data.partner.fields.foo.default = "ABC"; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
', + }); + + // switch to edit mode and edit the foo field + form.$buttons.find('.o_form_button_edit').click(); + assert.strictEqual(form.$('.o_form_input').val(), 'ABC', 'input should contain ABC'); + + form.$buttons.find('.o_form_button_cancel').click(); + + assert.strictEqual($('.modal').length, 0, + 'there should not be a confirm modal'); + + form.destroy(); + }); + + QUnit.test('discard changes on a duplicated record', function (assert) { + assert.expect(2); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
', + res_id: 1, + viewOptions: {sidebar: true}, + }); + + form.$buttons.find('.o_form_button_edit').click(); + form.$('input').val("tralala").trigger('input'); + form.$buttons.find('.o_form_button_save').click(); + + form.sidebar.$('a:contains(Duplicate)').click(); + + assert.strictEqual(form.$('.o_form_input').val(), 'tralala', 'input should contain ABC'); + + form.$buttons.find('.o_form_button_cancel').click(); + + assert.strictEqual($('.modal').length, 0, + 'there should not be a confirm modal'); + + form.destroy(); + }); + QUnit.test('switching to another record from a dirty one', function (assert) { assert.expect(11);