Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cute-walls-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/table-core': patch
---

Fixed table-core `row.getIsAllSubRowsSelected` now returns false when subrows are unselectable ()
81 changes: 40 additions & 41 deletions packages/table-core/src/features/RowSelection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export interface RowSelectionRow {
*/
getCanSelectSubRows: () => boolean
/**
* Returns whether or not all of the row's sub rows are selected.
* Returns whether or not all of the row's selectable sub rows are selected.
* @link [API Docs](https://tanstack.com/table/v8/docs/api/features/row-selection#getisallsubrowsselected)
* @link [Guide](https://tanstack.com/table/v8/docs/guide/row-selection)
*/
Expand All @@ -88,7 +88,7 @@ export interface RowSelectionRow {
*/
getIsSelected: () => boolean
/**
* Returns whether or not some of the row's sub rows are selected.
* Returns whether or not some of the row's selectable sub rows are selected.
* @link [API Docs](https://tanstack.com/table/v8/docs/api/features/row-selection#getissomeselected)
* @link [Guide](https://tanstack.com/table/v8/docs/guide/row-selection)
*/
Expand Down Expand Up @@ -503,13 +503,14 @@ export const RowSelection: TableFeature = {
}

row.getIsSomeSelected = () => {
const { rowSelection } = table.getState()
return isSubRowSelected(row, rowSelection, table) === 'some'
const { selectableCount, selectedCount } = getSubRowSelectionsCount(row);
return selectedCount > 0 && selectedCount < selectableCount;
}

row.getIsAllSubRowsSelected = () => {
const { rowSelection } = table.getState()
return isSubRowSelected(row, rowSelection, table) === 'all'
const { selectableCount, selectedCount } = getSubRowSelectionsCount(row);

return selectedCount > 0 && selectedCount === selectableCount;
}

row.getCanSelect = () => {
Expand Down Expand Up @@ -636,43 +637,41 @@ export function isRowSelected<TData extends RowData>(
return selection[row.id] ?? false
}

export function isSubRowSelected<TData extends RowData>(
row: Row<TData>,
selection: Record<string, boolean>,
table: Table<TData>,
): boolean | 'some' | 'all' {
if (!row.subRows?.length) return false

let allChildrenSelected = true
let someSelected = false

row.subRows.forEach((subRow) => {
// Bail out early if we know both of these
if (someSelected && !allChildrenSelected) {
return
}

if (subRow.getCanSelect()) {
if (isRowSelected(subRow, selection)) {
someSelected = true
} else {
allChildrenSelected = false
/**
* Determines the number of selectable sub-rows and selected sub-rows (checked via BFS across all nested sub-rows).
*
* @param row The table row to evaluate.
* @returns The number of sub-rows that satisfy the condition.
*/
export function getSubRowSelectionsCount<TData extends RowData>(row: Row<TData>): { selectableCount: number, selectedCount: number } {
const q = [...row.subRows];
let selectableCount = 0;
let selectedCount = 0;
let index = 0;
while (index < q.length) {
const node = q[index]!;
if (node.getCanSelect()) {
selectableCount += 1;
if (node.getIsSelected()) {
selectedCount += 1;
}
}
q.push(...node.subRows);
index += 1;
}

// Check row selection of nested subrows
if (subRow.subRows && subRow.subRows.length) {
const subRowChildrenSelected = isSubRowSelected(subRow, selection, table)
if (subRowChildrenSelected === 'all') {
someSelected = true
} else if (subRowChildrenSelected === 'some') {
someSelected = true
allChildrenSelected = false
} else {
allChildrenSelected = false
}
}
})
return { selectableCount, selectedCount };
}

return allChildrenSelected ? 'all' : someSelected ? 'some' : false
export function isSubRowSelected<TData extends RowData>(
row: Row<TData>,
_selection: Record<string, boolean>,
_table: Table<TData>,
): boolean | 'some' | 'all' {
if (row.getIsSomeSelected()) {
return 'some';
} else if (row.getIsAllSubRowsSelected()) {
return 'all';
}
return false;
}
Loading