diff --git a/addons/web/static/src/js/chrome/view_manager.js b/addons/web/static/src/js/chrome/view_manager.js index aa0b383fd92..bc441f7accf 100644 --- a/addons/web/static/src/js/chrome/view_manager.js +++ b/addons/web/static/src/js/chrome/view_manager.js @@ -547,7 +547,7 @@ var ViewManager = Widget.extend(ControlPanelMixin, { * * @param {Object} action_data the action descriptor data * @param {String} action_data.name the action name, used to uniquely identify the action to find and execute it - * @param {String} [action_data.special=null] special action handlers (currently: only ``'cancel'``) + * @param {String} [action_data.special=null] special action handlers, closes the dialog if set * @param {String} [action_data.type='workflow'] the action type, if present, one of ``'object'``, ``'action'`` or ``'workflow'`` * @param {Object} [action_data.context=null] additional action context, to add to the current context * @param {DataSet} dataset a dataset object used to communicate with the server @@ -589,7 +589,7 @@ var ViewManager = Widget.extend(ControlPanelMixin, { } }; - if (action_data.special === 'cancel') { + if (action_data.special) { return handler({"type":"ir.actions.act_window_close"}); } else if (action_data.type === "object") { var args = record_id ? [[record_id]] : [this.env.ids]; 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 99d21552be6..4239edbb199 100644 --- a/addons/web/static/src/js/views/form/form_controller.js +++ b/addons/web/static/src/js/views/form/form_controller.js @@ -334,9 +334,9 @@ var FormController = BasicController.extend({ d.resolve(); }); def = d.promise(); - } else if (attrs.special) { + } else if (attrs.special === 'cancel') { def = this._callButtonAction(attrs, event.data.record); - } else { + } else if (!attrs.special || attrs.special === 'save') { // save the record but don't switch to readonly mode def = this.saveRecord(this.handle, { stayInEdit: true, diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js index 7afb8545934..ec41f21bfc1 100644 --- a/addons/web/static/tests/views/form_tests.js +++ b/addons/web/static/tests/views/form_tests.js @@ -1453,6 +1453,40 @@ QUnit.module('Views', { form.$('button').eq(1).click(); assert.strictEqual(writeCount, 1, "should not have triggered a write"); assert.strictEqual(executeActionCount, 2, "should have triggered a execute action"); + + form.destroy(); + }); + + QUnit.test('buttons with attr "special=save" save', function (assert) { + assert.expect(4); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
', + res_id: 1, + intercepts: { + execute_action: function () { + assert.step('execute_action'); + }, + }, + mockRPC: function (route, args) { + assert.step(args.method); + return this._super(route, args); + }, + viewOptions: { + mode: 'edit', + }, + }); + + form.$('input').val("tralala").trigger('input'); // make the record dirty + form.$('button').click(); // click on Save + assert.verifySteps(['read', 'write', 'execute_action']); + form.destroy(); }); diff --git a/doc/reference/views.rst b/doc/reference/views.rst index 4dedb51b95c..ce931aad417 100644 --- a/doc/reference/views.rst +++ b/doc/reference/views.rst @@ -350,7 +350,13 @@ system. Available semantic components are: ``button`` call into the Odoo system, similar to :ref:`list view buttons -