Skip to content

Commit

Permalink
fix(datatable): Fix updating the header checkbox when there are no ro…
Browse files Browse the repository at this point in the history
…ws 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
  • Loading branch information
material-web-copybara authored and allan-chen committed Sep 3, 2020
1 parent d3387f5 commit 2ccf996
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 8 deletions.
4 changes: 3 additions & 1 deletion packages/mdc-data-table/component.ts
Expand Up @@ -231,7 +231,9 @@ export class MDCDataTable extends MDCComponent<MDCDataTableFoundation> {
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(
Expand Down
9 changes: 5 additions & 4 deletions packages/mdc-data-table/foundation.ts
Expand Up @@ -286,12 +286,13 @@ export class MDCDataTableFoundation extends MDCFoundation<MDCDataTableAdapter> {
* 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);
Expand Down
19 changes: 16 additions & 3 deletions packages/mdc-data-table/test/component.test.ts
Expand Up @@ -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<HTMLElement>(`.${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',
() => {
Expand Down Expand Up @@ -696,9 +709,9 @@ describe('MDCDataTable', () => {
() => {
const {component} = setupTest({withoutRowSelection: true});
expect(() => {
component.destroy();
}).not.toThrowError();
});
component.destroy();
}).not.toThrowError();
});
});

describe('Progress indicator', () => {
Expand Down
18 changes: 18 additions & 0 deletions packages/mdc-data-table/test/foundation.test.ts
Expand Up @@ -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();
Expand Down

0 comments on commit 2ccf996

Please sign in to comment.