From 2ccf996cc417b888d7ac4ceebdfa4160464a0bb1 Mon Sep 17 00:00:00 2001 From: Material Web Team Date: Tue, 1 Sep 2020 17:42:41 -0700 Subject: [PATCH] fix(datatable): Fix updating the header checkbox when there are no rows in a datatable This change has two major pieces, one is prioritizing unchecking the header checkbox when there are no selected rows over the selected rows == number of rows comparison. The second is changing |isRowsSelectable| to return true if the header checkbox is present even if the table has no rows. BREAKING CHANGE: Header checkboxes will now be unchecked if layout is called when there are no rows. PiperOrigin-RevId: 329616597 --- packages/mdc-data-table/component.ts | 4 +++- packages/mdc-data-table/foundation.ts | 9 +++++---- .../mdc-data-table/test/component.test.ts | 19 ++++++++++++++++--- .../mdc-data-table/test/foundation.test.ts | 18 ++++++++++++++++++ 4 files changed, 42 insertions(+), 8 deletions(-) diff --git a/packages/mdc-data-table/component.ts b/packages/mdc-data-table/component.ts index 44092f46733..6fd4929d86d 100644 --- a/packages/mdc-data-table/component.ts +++ b/packages/mdc-data-table/component.ts @@ -231,7 +231,9 @@ export class MDCDataTable extends MDCComponent { isCheckboxAtRowIndexChecked: (rowIndex: number) => this.rowCheckboxList[rowIndex].checked, isHeaderRowCheckboxChecked: () => this.headerRowCheckbox.checked, - isRowsSelectable: () => !!this.root.querySelector(selectors.ROW_CHECKBOX), + isRowsSelectable: () => + !!this.root.querySelector(selectors.ROW_CHECKBOX) || + !!this.root.querySelector(selectors.HEADER_ROW_CHECKBOX), notifyRowSelectionChanged: (data: MDCDataTableRowSelectionChangedEventDetail) => { this.emit( diff --git a/packages/mdc-data-table/foundation.ts b/packages/mdc-data-table/foundation.ts index 342f6c6c33a..8cd071b4916 100644 --- a/packages/mdc-data-table/foundation.ts +++ b/packages/mdc-data-table/foundation.ts @@ -286,12 +286,13 @@ export class MDCDataTableFoundation extends MDCFoundation { * Updates header row checkbox state based on number of rows selected. */ private setHeaderRowCheckboxState() { - if (this.adapter.getSelectedRowCount() === this.adapter.getRowCount()) { - this.adapter.setHeaderRowCheckboxChecked(true); + if (this.adapter.getSelectedRowCount() === 0) { + this.adapter.setHeaderRowCheckboxChecked(false); this.adapter.setHeaderRowCheckboxIndeterminate(false); - } else if (this.adapter.getSelectedRowCount() === 0) { + } else if ( + this.adapter.getSelectedRowCount() === this.adapter.getRowCount()) { + this.adapter.setHeaderRowCheckboxChecked(true); this.adapter.setHeaderRowCheckboxIndeterminate(false); - this.adapter.setHeaderRowCheckboxChecked(false); } else { this.adapter.setHeaderRowCheckboxIndeterminate(true); this.adapter.setHeaderRowCheckboxChecked(false); diff --git a/packages/mdc-data-table/test/component.test.ts b/packages/mdc-data-table/test/component.test.ts index 1fa2d1f5442..c6ffac5d857 100644 --- a/packages/mdc-data-table/test/component.test.ts +++ b/packages/mdc-data-table/test/component.test.ts @@ -516,6 +516,19 @@ describe('MDCDataTable', () => { component.destroy(); }); + describe('Removing Rows', () => { + it('removes all rows while the header checkbox is checked.', () => { + const {component, root, adapter} = setupTest(); + adapter.setHeaderRowCheckboxChecked(true); + expect(adapter.isHeaderRowCheckboxChecked()).toBe(true); + const tableContent = + root.querySelector(`.${cssClasses.CONTENT}`); + tableContent!.textContent = ``; + component.layout(); + expect(adapter.isHeaderRowCheckboxChecked()).toBe(false); + }); + }); + describe('Column sorting', () => { it('emits sort event when clicked on sort button of sortable column header', () => { @@ -696,9 +709,9 @@ describe('MDCDataTable', () => { () => { const {component} = setupTest({withoutRowSelection: true}); expect(() => { - component.destroy(); - }).not.toThrowError(); - }); + component.destroy(); + }).not.toThrowError(); + }); }); describe('Progress indicator', () => { diff --git a/packages/mdc-data-table/test/foundation.test.ts b/packages/mdc-data-table/test/foundation.test.ts index 353821cf6bd..0a1254fe431 100644 --- a/packages/mdc-data-table/test/foundation.test.ts +++ b/packages/mdc-data-table/test/foundation.test.ts @@ -124,6 +124,24 @@ describe('MDCDataTableFoundation', () => { expect(mockAdapter.setHeaderRowCheckboxChecked).toHaveBeenCalledTimes(1); }); + it('#layout should set header row checkbox unchecked when there are no rows', + () => { + const {foundation, mockAdapter} = setupTest(); + + mockAdapter.isRowsSelectable.and.returnValue(true); + mockAdapter.getSelectedRowCount.and.returnValue(0); + mockAdapter.getRowCount.and.returnValue(0); + + foundation.layout(); + expect(mockAdapter.setHeaderRowCheckboxIndeterminate) + .toHaveBeenCalledWith(false); + expect(mockAdapter.setHeaderRowCheckboxIndeterminate) + .toHaveBeenCalledTimes(1); + expect(mockAdapter.setHeaderRowCheckboxChecked) + .toHaveBeenCalledWith(false); + expect(mockAdapter.setHeaderRowCheckboxChecked).toHaveBeenCalledTimes(1); + }); + it('#layout should set header row checkbox indeterminate when some of the checkboxes are checked', () => { const {foundation, mockAdapter} = setupTest();