Skip to content

fix(table-core): include sub-rows in flatRows when maxLeafRowFilterDepth truncates recursion#6361

Open
JSap0914 wants to merge 2 commits into
TanStack:betafrom
JSap0914:fix/filterRowModelFromRoot-flatRows-maxLeafRowFilterDepth-5987
Open

fix(table-core): include sub-rows in flatRows when maxLeafRowFilterDepth truncates recursion#6361
JSap0914 wants to merge 2 commits into
TanStack:betafrom
JSap0914:fix/filterRowModelFromRoot-flatRows-maxLeafRowFilterDepth-5987

Conversation

@JSap0914

@JSap0914 JSap0914 commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Bug

Closes #5987

When filterRowModelFromRoot skips recursing into sub-rows because depth >= maxLeafRowFilterDepth, the parent row's sub-rows remain accessible through row.subRows but were never added to newFilteredFlatRows. This makes flatRows an incomplete flat representation of the visible tree.

Root cause

// filterRowsUtils.ts — filterRowModelFromRoot
if (pass) {
  if (row.subRows.length && depth < maxDepth) {
    // recursion adds sub-rows to newFilteredFlatRows ✓
    newRow.subRows = recurseFilterRows(row.subRows, depth + 1)
  }
  // when depth >= maxDepth, sub-rows are on row.subRows but
  // NEVER pushed to newFilteredFlatRows ← bug
  newFilteredFlatRows.push(row)
}

Impact

column.getFacetedUniqueValues() returns inconsistent counts:

  • Before any filter: flatRows = all rows at all depths (from preRowModel) — counts sub-rows ✓
  • After filtering with maxLeafRowFilterDepth: 0: flatRows = only passing top-level rows — misses sub-rows ✗

Fix

Added addSubRowsToFlatArrays helper that recursively pushes sub-rows into flatRows and rowsById when a passing row has sub-rows that were skipped due to depth >= maxDepth.

Verification

New test file: packages/table-core/tests/unit/features/column-filtering/filterRowsUtils.test.ts

Test Before After
No filter: flatRows has all 5 rows
maxLeafRowFilterDepth=100: sub-rows filtered normally
maxLeafRowFilterDepth=0, Alice passes: flatRows=3 (Alice+Charlie+Dave) ❌ got 1
maxLeafRowFilterDepth=0, sub-row consistency ❌ got 1
Tests  4 passed (4)

All 359 existing tests continue to pass.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed hierarchical table filtering so that when filtering halts at a maximum depth, the visible nested sub-rows are still included and stay aligned in the flattened row list.
    • Improved consistency between filtered and unfiltered results for nested rows.
  • Tests
    • Added unit tests covering nested column filtering behavior, including maxLeafRowFilterDepth differences and expected flatRows counts.
…pth truncates recursion

When filterRowModelFromRoot skips recursing into sub-rows because the
current depth >= maxLeafRowFilterDepth, the parent row's sub-rows are
still accessible through row.subRows and remain visible in the table.
However, these sub-rows were never added to newFilteredFlatRows, making
flatRows an incomplete flat representation of the visible tree.

This causes getFacetedUniqueValues() to return different counts before
and after filtering when maxLeafRowFilterDepth is set: before filtering
flatRows contains all rows at all depths (via preRowModel), but after
filtering flatRows only contains passing top-level rows.

Fix: add addSubRowsToFlatArrays helper that recursively pushes sub-rows
(and their descendants) into flatRows and rowsById when a passing row
has sub-rows that were skipped due to depth >= maxDepth.

Fixes TanStack#5987
Copilot AI review requested due to automatic review settings June 30, 2026 03:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1128f10c-2774-4894-b4e6-8962343464fa

📥 Commits

Reviewing files that changed from the base of the PR and between d5d357b and 17dbb8e.

📒 Files selected for processing (2)
  • packages/table-core/src/features/column-filtering/filterRowsUtils.ts
  • packages/table-core/tests/unit/features/column-filtering/filterRowsUtils.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/table-core/src/features/column-filtering/filterRowsUtils.ts
  • packages/table-core/tests/unit/features/column-filtering/filterRowsUtils.test.ts

📝 Walkthrough

Walkthrough

Adds recursive sub-row flattening in filterRowsUtils.ts so root-down filtering keeps visible nested rows in flatRows when maxLeafRowFilterDepth stops recursion. A new unit test file checks flatRows counts across unfiltered, depth-100, and depth-0 filtering cases.

Changes

flatRows fix for maxLeafRowFilterDepth

Layer / File(s) Summary
Helper and depth-limit handling
packages/table-core/src/features/column-filtering/filterRowsUtils.ts
Defines a recursive helper that adds nested sub-rows to flatRows and rowsById, then uses it when root-down filtering stops at maxLeafRowFilterDepth.
Filtered row model tests
packages/table-core/tests/unit/features/column-filtering/filterRowsUtils.test.ts
Adds a nested table test setup and verifies flatRows output for unfiltered, depth-100, and depth-0 filtering scenarios.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 When depth said “halt,” the rows still stayed,
In flatRows, nested paths არიან laid.
A bunny hops through trees of lines,
And every sub-row neatly shines.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main fix: keeping sub-rows in flatRows when recursion is truncated by maxLeafRowFilterDepth.
Linked Issues check ✅ Passed The change restores skipped sub-rows to the filtered flat row model, which addresses the maxLeafRowFilterDepth: 0 consistency issue.
Out of Scope Changes check ✅ Passed The diff stays focused on filtering internals and unit tests, with no unrelated feature work or public API changes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/table-core/src/features/column-filtering/filterRowsUtils.ts`:
- Around line 164-170: The depth-limit branch in recurseFilterRows is appending
visible subRows after the current row, which breaks the usual
descendant-before-parent flatRows order. Update the branch that handles
row.subRows with depth >= maxDepth so it preserves the same traversal ordering
as the normal recursion path, using addSubRowsToFlatArrays and the surrounding
filtered row accumulation logic to keep flatRows consistent regardless of
maxLeafRowFilterDepth.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 10271759-df3d-4e9f-b330-c4cb64286554

📥 Commits

Reviewing files that changed from the base of the PR and between b7b05a9 and d5d357b.

📒 Files selected for processing (2)
  • packages/table-core/src/features/column-filtering/filterRowsUtils.ts
  • packages/table-core/tests/unit/features/column-filtering/filterRowsUtils.test.ts
Comment on lines +164 to +170
// When sub-rows exist but weren't recursed into (depth >= maxDepth),
// they are still visible in the row tree. Add them to flatRows so that
// flatRows is a complete flat representation of all visible rows,
// consistent with the no-filter case.
if (row.subRows.length && depth >= maxDepth) {
addSubRowsToFlatArrays(row.subRows, newFilteredFlatRows, newFilteredRowsById)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve flatRows traversal order in the depth-limit branch.

recurseFilterRows() normally appends descendants before their parent, but this branch pushes row first and only then appends the skipped descendants. That makes flatRows order change when the only thing that changes is maxLeafRowFilterDepth.

Suggested fix
-        filteredRows.push(row)
-        newFilteredFlatRows.push(row)
-        newFilteredRowsById[row.id] = row
         // When sub-rows exist but weren't recursed into (depth >= maxDepth),
         // they are still visible in the row tree. Add them to flatRows so that
         // flatRows is a complete flat representation of all visible rows,
         // consistent with the no-filter case.
         if (row.subRows.length && depth >= maxDepth) {
           addSubRowsToFlatArrays(row.subRows, newFilteredFlatRows, newFilteredRowsById)
         }
+        filteredRows.push(row)
+        newFilteredFlatRows.push(row)
+        newFilteredRowsById[row.id] = row
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// When sub-rows exist but weren't recursed into (depth >= maxDepth),
// they are still visible in the row tree. Add them to flatRows so that
// flatRows is a complete flat representation of all visible rows,
// consistent with the no-filter case.
if (row.subRows.length && depth >= maxDepth) {
addSubRowsToFlatArrays(row.subRows, newFilteredFlatRows, newFilteredRowsById)
}
// When sub-rows exist but weren't recursed into (depth >= maxDepth),
// they are still visible in the row tree. Add them to flatRows so that
// flatRows is a complete flat representation of all visible rows,
// consistent with the no-filter case.
if (row.subRows.length && depth >= maxDepth) {
addSubRowsToFlatArrays(row.subRows, newFilteredFlatRows, newFilteredRowsById)
}
filteredRows.push(row)
newFilteredFlatRows.push(row)
newFilteredRowsById[row.id] = row
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/table-core/src/features/column-filtering/filterRowsUtils.ts` around
lines 164 - 170, The depth-limit branch in recurseFilterRows is appending
visible subRows after the current row, which breaks the usual
descendant-before-parent flatRows order. Update the branch that handles
row.subRows with depth >= maxDepth so it preserves the same traversal ordering
as the normal recursion path, using addSubRowsToFlatArrays and the surrounding
filtered row accumulation logic to keep flatRows consistent regardless of
maxLeafRowFilterDepth.
@nx-cloud

nx-cloud Bot commented Jun 30, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 17dbb8e

Command Status Duration Result
nx affected --targets=test:eslint,test:sherif,t... ❌ Failed 6m 1s View ↗
nx run-many --targets=build --exclude=examples/** ✅ Succeeded 26s View ↗

☁️ Nx Cloud last updated this comment at 2026-06-30 19:12:44 UTC

@pkg-pr-new

pkg-pr-new Bot commented Jun 30, 2026

Copy link
Copy Markdown
More templates

@tanstack/angular-table

npm i https://pkg.pr.new/TanStack/table/@tanstack/angular-table@6361

@tanstack/angular-table-devtools

npm i https://pkg.pr.new/TanStack/table/@tanstack/angular-table-devtools@6361

@tanstack/lit-table

npm i https://pkg.pr.new/TanStack/table/@tanstack/lit-table@6361

@tanstack/match-sorter-utils

npm i https://pkg.pr.new/TanStack/table/@tanstack/match-sorter-utils@6361

@tanstack/preact-table

npm i https://pkg.pr.new/TanStack/table/@tanstack/preact-table@6361

@tanstack/preact-table-devtools

npm i https://pkg.pr.new/TanStack/table/@tanstack/preact-table-devtools@6361

@tanstack/react-table

npm i https://pkg.pr.new/TanStack/table/@tanstack/react-table@6361

@tanstack/react-table-devtools

npm i https://pkg.pr.new/TanStack/table/@tanstack/react-table-devtools@6361

@tanstack/solid-table

npm i https://pkg.pr.new/TanStack/table/@tanstack/solid-table@6361

@tanstack/solid-table-devtools

npm i https://pkg.pr.new/TanStack/table/@tanstack/solid-table-devtools@6361

@tanstack/svelte-table

npm i https://pkg.pr.new/TanStack/table/@tanstack/svelte-table@6361

@tanstack/table-core

npm i https://pkg.pr.new/TanStack/table/@tanstack/table-core@6361

@tanstack/table-devtools

npm i https://pkg.pr.new/TanStack/table/@tanstack/table-devtools@6361

@tanstack/vue-table

npm i https://pkg.pr.new/TanStack/table/@tanstack/vue-table@6361

@tanstack/vue-table-devtools

npm i https://pkg.pr.new/TanStack/table/@tanstack/vue-table-devtools@6361

commit: 17dbb8e

@nx-cloud nx-cloud Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nx Cloud is proposing a fix for your failed CI:

We moved filteredRowModel and filterFns from the constructTable features option into the top-level tableFeatures() call, which is where TypeScript resolves valid filter function key names via ExtractFilterFnKeys<TFeatures>. This fixes both TS2322 ('includesString' not assignable) and TS2353 (filteredRowModel not a known property on the features object), bringing the test file in line with the canonical pattern used elsewhere in the workspace.

Tip

We verified this fix by re-running @tanstack/table-core:test:types.

diff --git a/packages/table-core/tests/unit/features/column-filtering/filterRowsUtils.test.ts b/packages/table-core/tests/unit/features/column-filtering/filterRowsUtils.test.ts
index 2a06d8d8..fe30f6fa 100644
--- a/packages/table-core/tests/unit/features/column-filtering/filterRowsUtils.test.ts
+++ b/packages/table-core/tests/unit/features/column-filtering/filterRowsUtils.test.ts
@@ -12,7 +12,12 @@ import type { ColumnDef, ColumnFiltersState } from '../../../../src'
 
 type Row = { name: string; subRows?: Row[] }
 
-const features = tableFeatures({ ...coreFeatures, columnFilteringFeature })
+const features = tableFeatures({
+  ...coreFeatures,
+  columnFilteringFeature,
+  filteredRowModel: createFilteredRowModel(),
+  filterFns,
+})
 
 function makeNestedTable(opts?: {
   maxLeafRowFilterDepth?: number
@@ -51,8 +56,6 @@ function makeNestedTable(opts?: {
     },
     features: {
       ...features,
-      filteredRowModel: createFilteredRowModel(),
-      filterFns,
       coreReactivityFeature: storeReactivityBindings(),
     },
   })

Because this branch comes from a fork, it is not possible for us to apply fixes directly, but you can apply the changes locally using the available options below.

Apply changes locally with:

npx nx-cloud apply-locally dqWa-F83o

Apply fix locally with your editor ↗   View interactive diff ↗



🎓 Learn more about Self-Healing CI on nx.dev

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants