From 31ec900bb015e5f2df464d54f4818f8201d0de44 Mon Sep 17 00:00:00 2001 From: Julien Mougenot Date: Tue, 17 Sep 2019 15:26:35 +0000 Subject: [PATCH] [FIX] web: list selectors synchronisation Changed the way the header selector behave when the selection changes. Before this commit, the header selector was only checked when clicked and was unchecked as soon as any other record was unchecked. Now, the header selector reflects the current visible selection: if all of the other visible selectors are checked, it will be checked. Folded records are not considered visible, thus only records from active groups and from the current pager will be taken into account. closes odoo/odoo#36522 Signed-off-by: VincentSchippefilt --- .../static/src/js/views/list/list_renderer.js | 20 ++++++--- addons/web/static/tests/views/list_tests.js | 43 +++++++++++++++++++ 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/addons/web/static/src/js/views/list/list_renderer.js b/addons/web/static/src/js/views/list/list_renderer.js index ed5af4c96bb..1fc6b7006b9 100644 --- a/addons/web/static/src/js/views/list/list_renderer.js +++ b/addons/web/static/src/js/views/list/list_renderer.js @@ -877,11 +877,18 @@ var ListRenderer = BasicRenderer.extend({ * @private */ _updateSelection: function () { - var $selectedRows = this.$('tbody .o_list_record_selector input:checked') - .closest('tr'); - this.selection = _.map($selectedRows, function (row) { - return $(row).data('id'); + this.selection = []; + var self = this; + var $inputs = this.$('tbody .o_list_record_selector input:visible:not(:disabled)'); + var allChecked = $inputs.length > 0; + $inputs.each(function (index, input) { + if (input.checked) { + self.selection.push($(input).closest('tr').data('id')); + } else { + allChecked = false; + } }); + this.$('thead .o_list_record_selector input').prop('checked', allChecked); this.trigger_up('selection_changed', { selection: this.selection }); this._updateFooter(); }, @@ -1012,9 +1019,6 @@ var ListRenderer = BasicRenderer.extend({ _onSelectRecord: function (ev) { ev.stopPropagation(); this._updateSelection(); - if (!$(ev.currentTarget).find('input').prop('checked')) { - this.$('thead .o_list_record_selector input').prop('checked', false); - } }, /** * @private @@ -1031,11 +1035,13 @@ var ListRenderer = BasicRenderer.extend({ _onToggleGroup: function (ev) { ev.preventDefault(); ev.stopPropagation(); + var self = this; var group = $(ev.currentTarget).closest('tr').data('group'); if (group.count) { this.trigger_up('toggle_group', { group: group, onSuccess: function() { + self._updateSelection(); // Refocus the header after re-render unless the user // already focused something else by now if (document.activeElement.tagName === 'BODY') { diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js index 4fea02ae3e9..28eff515ffa 100644 --- a/addons/web/static/tests/views/list_tests.js +++ b/addons/web/static/tests/views/list_tests.js @@ -1073,6 +1073,49 @@ QUnit.module('Views', { list.destroy(); }); + QUnit.test('head selector is toggled by the other selectors', async function (assert) { + assert.expect(6); + + const list = await createView({ + arch: '', + data: this.data, + groupBy: ['bar'], + model: 'foo', + View: ListView, + }); + + assert.ok(!list.$('thead .o_list_record_selector input')[0].checked, + "Head selector should be unchecked"); + + await testUtils.dom.click(list.$('.o_group_header:first()')); + await testUtils.dom.click(list.$('thead .o_list_record_selector input')); + + assert.containsN(list, 'tbody .o_list_record_selector input:checked', + 3, "All visible checkboxes should be checked"); + + await testUtils.dom.click(list.$('.o_group_header:last()')); + + assert.ok(!list.$('thead .o_list_record_selector input')[0].checked, + "Head selector should be unchecked"); + + await testUtils.dom.click(list.$('tbody .o_list_record_selector input:last()')); + + assert.ok(list.$('thead .o_list_record_selector input')[0].checked, + "Head selector should be checked"); + + await testUtils.dom.click(list.$('tbody .o_list_record_selector:first() input')); + + assert.ok(!list.$('thead .o_list_record_selector input')[0].checked, + "Head selector should be unchecked"); + + await testUtils.dom.click(list.$('.o_group_header:first()')); + + assert.ok(list.$('thead .o_list_record_selector input')[0].checked, + "Head selector should be checked"); + + list.destroy(); + }); + QUnit.test('selection is reset on reload', async function (assert) { assert.expect(5);