diff --git a/docs/core/interfaces/datatable-adapter.interface.md b/docs/core/interfaces/datatable-adapter.interface.md index c057be9fbe..12b76dc159 100644 --- a/docs/core/interfaces/datatable-adapter.interface.md +++ b/docs/core/interfaces/datatable-adapter.interface.md @@ -81,6 +81,7 @@ An array of [`DataRow`](../../../lib/core/src/lib/datatable/data/data-row.model. ```ts interface DataRow { isSelected: boolean; + isSelectable?: boolean; isDropTarget?: boolean; cssClass?: string; hasValue(key: string): boolean; diff --git a/lib/core/src/lib/datatable/components/datatable/datatable.component.html b/lib/core/src/lib/datatable/components/datatable/datatable.component.html index ac4d4ff2b2..bb28e7ffa0 100644 --- a/lib/core/src/lib/datatable/components/datatable/datatable.component.html +++ b/lib/core/src/lib/datatable/components/datatable/datatable.component.html @@ -213,6 +213,7 @@ tabindex="0"> { } }); + it('should update only selectable rows on "select all" click', () => { + const data = new ObjectDataTableAdapter([{}, {}, {}], []); + const rows = data.getRows(); + + rows[0].isSelectable = false; + + dataTable.data = data; + dataTable.multiselect = true; + dataTable.ngAfterContentInit(); + + dataTable.onSelectAllClick({ checked: true } as MatCheckboxChange); + expect(dataTable.isSelectAllChecked).toBe(true); + for (let i = 0; i < rows.length; i++) { + if (i === 0) { + expect(rows[i].isSelected).toBe(false); + continue; + } + + expect(rows[i].isSelected).toBe(true); + } + + dataTable.onSelectAllClick({ checked: false } as MatCheckboxChange); + expect(dataTable.isSelectAllChecked).toBe(false); + for (let i = 0; i < rows.length; i++) { + expect(rows[i].isSelected).toBe(false); + } + }); + it('should allow "select all" calls with no rows', () => { dataTable.multiselect = true; dataTable.ngOnChanges({ data: new SimpleChange('123', {}, true) }); diff --git a/lib/core/src/lib/datatable/components/datatable/datatable.component.ts b/lib/core/src/lib/datatable/components/datatable/datatable.component.ts index 8cda699571..66ddc4a973 100644 --- a/lib/core/src/lib/datatable/components/datatable/datatable.component.ts +++ b/lib/core/src/lib/datatable/components/datatable/datatable.component.ts @@ -446,7 +446,7 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges, } convertToRowsData(rows: any[]): ObjectDataRow[] { - return rows.map((row) => new ObjectDataRow(row, row.isSelected)); + return rows.map((row) => new ObjectDataRow(row, row.isSelected, row?.isSelectable)); } convertToColumnsData(columns: any[]): ObjectDataColumn[] { @@ -589,7 +589,7 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges, } private handleRowSelection(row: DataRow, e: KeyboardEvent | MouseEvent) { - if (!this.data) { + if (!this.data || !row?.isSelectable) { return; } @@ -713,10 +713,10 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges, this.isSelectAllIndeterminate = false; if (this.multiselect) { - const rows = this.data.getRows(); - if (rows && rows.length > 0) { - for (let i = 0; i < rows.length; i++) { - this.selectRow(rows[i], matCheckboxChange.checked); + const selectableRows = this.data.getRows().filter(row => row?.isSelectable); + if (selectableRows && selectableRows.length > 0) { + for (let i = 0; i < selectableRows.length; i++) { + this.selectRow(selectableRows[i], matCheckboxChange.checked); } } diff --git a/lib/core/src/lib/datatable/data/data-row.model.ts b/lib/core/src/lib/datatable/data/data-row.model.ts index d8ab579467..a0612f30cd 100644 --- a/lib/core/src/lib/datatable/data/data-row.model.ts +++ b/lib/core/src/lib/datatable/data/data-row.model.ts @@ -19,6 +19,7 @@ export interface DataRow { [key: string]: any; isSelected: boolean; + isSelectable?: boolean; isDropTarget?: boolean; cssClass?: string; id?: string; diff --git a/lib/core/src/lib/datatable/data/object-datarow.model.ts b/lib/core/src/lib/datatable/data/object-datarow.model.ts index dc1202ef4f..72a0f43989 100644 --- a/lib/core/src/lib/datatable/data/object-datarow.model.ts +++ b/lib/core/src/lib/datatable/data/object-datarow.model.ts @@ -21,7 +21,7 @@ import { DataRow } from './data-row.model'; // Simple implementation of the DataRow interface. export class ObjectDataRow implements DataRow { - constructor(private obj: any, public isSelected: boolean = false) { + constructor(private obj: any, public isSelected: boolean = false, public isSelectable: boolean = true) { if (!obj) { throw new Error('Object source not found'); }