diff --git a/addons/web/static/src/js/views/list/list_controller.js b/addons/web/static/src/js/views/list/list_controller.js index bd0322c92b0..f99ec19dea7 100644 --- a/addons/web/static/src/js/views/list/list_controller.js +++ b/addons/web/static/src/js/views/list/list_controller.js @@ -396,6 +396,7 @@ var ListController = BasicController.extend({ var nbInvalid = recordIds.length - validRecordIds.length; return new Promise(function (resolve, reject) { + var dialog; var rejectAndDiscard = function () { self.model.discardChanges(recordId); return self._confirmSave(recordId).then(reject); @@ -411,24 +412,33 @@ var ListController = BasicController.extend({ _t("Do you want to set the value on the %d valid selected records? (%d invalid)"), validRecordIds.length, nbInvalid); } - Dialog.confirm(self, message, { + dialog = Dialog.confirm(self, message, { confirm_callback: function () { - self.model.saveRecords(recordId, validRecordIds, fieldName) + return self.model.saveRecords(recordId, validRecordIds, fieldName) .then(function () { self._updateButtons('readonly'); var state = self.model.get(self.handle); - self.renderer.updateState(state, {}); - resolve(Object.keys(changes)); + return self.renderer.updateState(state, {}).then(function () { + resolve(Object.keys(changes)); + }); }) .guardedCatch(rejectAndDiscard); }, cancel_callback: rejectAndDiscard, }); } else { - Dialog.alert(self, _t("No valid record to save"), { + dialog = Dialog.alert(self, _t("No valid record to save"), { confirm_callback: rejectAndDiscard, }); } + dialog.on('closed', self, function () { + // we need to wait for the dialog to be actually closed, but + // the 'closed' event is triggered just before, and it prevents + // from focussing the cell + Promise.resolve().then(function () { + self.renderer.focusCell(recordId, node); + }); + }); }); }, /** diff --git a/addons/web/static/src/js/views/list/list_editable_renderer.js b/addons/web/static/src/js/views/list/list_editable_renderer.js index cd67feb0b34..b23b7a85e0a 100644 --- a/addons/web/static/src/js/views/list/list_editable_renderer.js +++ b/addons/web/static/src/js/views/list/list_editable_renderer.js @@ -276,6 +276,17 @@ ListRenderer.include({ var rowIndex = $row.prop('rowIndex') - 1; this._selectCell(rowIndex, 0); }, + /** + * Gives focus to a specific cell, given its row and its related column. + * + * @param {string} recordId + * @param {Object} column + */ + focusCell: function (recordId, column) { + var $row = this._getRow(recordId); + var cellIndex = this.columns.indexOf(column); + $row.find('.o_data_cell')[cellIndex].focus(); + }, /** * Returns the recordID associated to the line which is currently in edition * or null if there is no line in edition. diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js index ba61d49b78b..94f6ced9fc4 100644 --- a/addons/web/static/tests/views/list_tests.js +++ b/addons/web/static/tests/views/list_tests.js @@ -4480,7 +4480,7 @@ QUnit.module('Views', { }); QUnit.test('editable list view: multi edition', async function (assert) { - assert.expect(22); + assert.expect(24); var list = await createView({ View: ListView, @@ -4536,6 +4536,8 @@ QUnit.module('Views', { await testUtils.dom.click($('.modal .btn:contains(Cancel)')); assert.strictEqual(list.$('.o_data_row:eq(0) .o_data_cell').text(), 'yop10', "changes have been discarded and row is back to readonly"); + assert.strictEqual(document.activeElement, list.$('.o_data_row:eq(0) .o_data_cell:eq(1)')[0], + "focus should be given to the most recently edited cell after discard"); await testUtils.dom.click(list.$('.o_data_row:eq(0) .o_data_cell:eq(1)')); await testUtils.fields.editInput(list.$('.o_field_widget[name=int_field]'), 666); await testUtils.dom.click(list.$('.o_data_row:eq(1) .o_data_cell:eq(0)')); @@ -4548,6 +4550,8 @@ QUnit.module('Views', { assert.strictEqual(list.$('.o_data_row:eq(1) .o_data_cell').text(), "blip666", "the second row should be updated"); assert.containsNone(list, '.o_data_cell input.o_field_widget', "no field should be editable anymore"); + assert.strictEqual(document.activeElement, list.$('.o_data_row:eq(0) .o_data_cell:eq(1)')[0], + "focus should be given to the most recently edited cell after confirm"); list.destroy(); });