[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.

Task 2068280
This commit is contained in:
Julien Mougenot
2019-09-18 11:31:43 +00:00
committed by Aaron Bohy
parent 62452aad41
commit 8b6f3580d8
2 changed files with 56 additions and 8 deletions
@@ -996,11 +996,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();
},
@@ -1186,9 +1193,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
@@ -1209,7 +1213,8 @@ var ListRenderer = BasicRenderer.extend({
if (group.count) {
this.trigger_up('toggle_group', {
group: group,
onSuccess: function () {
onSuccess: () => {
this._updateSelection();
// Refocus the header after re-render unless the user
// already focused something else by now
if (document.activeElement.tagName === 'BODY') {
@@ -1143,6 +1143,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: '<tree><field name="foo"/><field name="bar"/></tree>',
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);