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 a9b9cacd9c9..12ef168c131 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 @@ -425,6 +425,10 @@ ListRenderer.include({ * in edit mode. This is the moment we save all accumulated changes on that * row, if needed (@see BasicController.saveRecord). * + * Note that we have to disable the focusable elements (inputs, ...) to + * prevent subsequent editions. These edits would be lost, because the list + * view only saves records when unselecting a row. + * * @returns {Deferred} The deferred resolves if the row was unselected (and * possibly removed). If may be rejected, when the row is dirty and the * user refuses to discard its changes. @@ -436,13 +440,23 @@ ListRenderer.include({ } var record = this.state.data[this.currentRow]; + var recordWidgets = this.allFieldWidgets[record.id]; + toggleWidgets(true); + var def = $.Deferred(); this.trigger_up('save_line', { recordID: record.id, onSuccess: def.resolve.bind(def), onFailure: def.reject.bind(def), }); - return def; + return def.fail(toggleWidgets.bind(null, false)); + + function toggleWidgets(disabled) { + _.each(recordWidgets, function (widget) { + var $el = widget.getFocusableElement(); + $el.prop('disabled', disabled); + }); + } }, //-------------------------------------------------------------------------- diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js index 0b754c2b5bb..ddfb985c3c1 100644 --- a/addons/web/static/tests/views/list_tests.js +++ b/addons/web/static/tests/views/list_tests.js @@ -1759,6 +1759,31 @@ QUnit.module('Views', { list.destroy(); }); + + QUnit.test('inputs are disabled when unselecting rows', function (assert) { + assert.expect(1); + + var list = createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: '', + mockRPC: function (route, args) { + if (args.method === 'write') { + assert.strictEqual($input.prop('disabled'), true, + "input should be disabled"); + } + return this._super.apply(this, arguments); + }, + }); + + list.$('td:contains(gnap)').click(); + var $input = list.$('tr.o_selected_row input[name="foo"]'); + $input.val('lemon').trigger('input'); + $input.trigger({type: 'keydown', which: $.ui.keyCode.DOWN}); + list.destroy(); + }); + }); });