diff --git a/addons/web/static/src/js/chrome/view_manager.js b/addons/web/static/src/js/chrome/view_manager.js index 45be7a9484a..5babc2cd0a5 100644 --- a/addons/web/static/src/js/chrome/view_manager.js +++ b/addons/web/static/src/js/chrome/view_manager.js @@ -171,10 +171,15 @@ var ViewManager = Widget.extend(ControlPanelMixin, { var options = _.extend({}, view_to_load.options); defs.push(self.switch_mode(view_to_load.type, options)); - return $.when.apply($, defs).then(function() { - if (self.flags.on_load) { - self.flags.on_load(self); - } + return $.when.apply($, defs); + }).then(function() { + if (self.flags.on_load) { + self.flags.on_load(self); + } + core.bus.on('clear_uncommitted_changes', self, function(chain_callbacks) { + chain_callbacks(function() { + return self.active_view.controller.canBeDiscarded(); + }); }); }); }, diff --git a/addons/web/static/src/js/views/abstract_controller.js b/addons/web/static/src/js/views/abstract_controller.js index 3d9db03eb1c..9344d3a9e21 100644 --- a/addons/web/static/src/js/views/abstract_controller.js +++ b/addons/web/static/src/js/views/abstract_controller.js @@ -63,6 +63,22 @@ var AbstractController = Widget.extend({ // Public //-------------------------------------------------------------------------- + /** + * Determines if we can discard the current state. For example, when the + * user open the 'home' screen, the view manager will call this method on + * the active view to make sure it is ok to open the home screen (and + * potentially loose all current state). + * + * Note that it returns a deferred, because the view could choose to ask the + * user if he agrees to discard. + * + * @override + * @returns {Deferred} If the deferred is resolved, we assume the changes + * can be discarded. If it is rejected, then we cannot discard. + */ + canBeDiscarded: function () { + return $.when(); + }, /** * Returns any special keys that may be useful when reloading the view to * get the same effect. This is necessary for saving the current view in 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 bf06c39034d..ff5510ae7e6 100644 --- a/addons/web/static/src/js/views/form/form_controller.js +++ b/addons/web/static/src/js/views/form/form_controller.js @@ -55,6 +55,32 @@ var FormController = BasicController.extend({ */ autofocus: function () { }, + /** + * Determines if we can discard the current change. If the model is not + * dirty, that is not a problem. However, if it is dirty, we have to ask + * the user for confirmation. + * + * @override + * @returns {Deferred} If the deferred is resolved, we assume the changes + * can be discarded. If it is rejected, then we cannot discard. + */ + canBeDiscarded: function () { + 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 ?"); + var def = $.Deferred(); + var options = { + title: _t("Warning"), + confirm_callback: function () { + this.on('closed', null, def.resolve.bind(def)); + }, + cancel_callback: def.reject.bind(def) + }; + var dialog = Dialog.confirm(this, message, options); + dialog.$modal.on('hidden.bs.modal', def.reject.bind(def)); + return def; + }, /** * @returns {boolean} */ @@ -146,7 +172,7 @@ var FormController = BasicController.extend({ */ renderPager: function ($node, options) { options = _.extend({}, options, { - validate: this._canBeDiscarded.bind(this), + validate: this.canBeDiscarded.bind(this), }); this._super($node, options); }, @@ -266,31 +292,6 @@ var FormController = BasicController.extend({ }); return def; }, - /** - * Determines if we can discard the current change. If the model is not - * dirty, that is not a problem. However, if it is dirty, we have to ask - * the user for confirmation. - * - * @returns {Deferred} If the deferred is resolved, we assume the changes - * can be discarded. If it has been rejected, then we cannot discard. - */ - _canBeDiscarded: function () { - 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 ?"); - var def = $.Deferred(); - var options = { - title: _t("Warning"), - confirm_callback: function () { - this.on('closed', null, def.resolve.bind(def)); - }, - cancel_callback: def.reject.bind(def) - }; - var dialog = Dialog.confirm(this, message, options); - dialog.$modal.on('hidden.bs.modal', def.reject.bind(def)); - return def; - }, /** * @override method from FieldManagerMixin * @param {string} id it is ignored, because we already know it. @@ -446,7 +447,7 @@ var FormController = BasicController.extend({ */ _onDiscardChange: function () { var self = this; - this._canBeDiscarded().then(function () { + this.canBeDiscarded().then(function () { self.model.discardChanges(self.handle); if (!self.model.isNew(self.handle)) { self._toReadOnlyMode();