Skip to content

Conversation

@riccardoperra
Copy link
Collaborator

@riccardoperra riccardoperra commented Feb 14, 2025

Those are some experiments with angularReactivityFeature. The goal of this pr is to remove the proxies and make the table reactive with signals directly via a custom feature.

createAngularTable/injectTable return value is currently a proxy into a proxy :

  • lazyInit -> needed to support required input signals. This basically schedule the table object creation in a microtask
  • proxifyTable -> needed to override table properties and make them reactive when the table signal changes

Using proxifyTable doesn't directly lead in issues after the new FlexRender implementation, but the returned table it's just a different object compared to the one obtained via (header|cell).getContext(), which the latter is not reactive.

Thanks to table features added in v9, we could move away from proxyTable by just overriding table/cell/header/column/row props recursively via TableFeature interface.

This allows to make all properties reactive via the same logic used by the table proxy right now using toComputed.

Overriding all properties can be costly because if there are a lot of elements, a potential reactive signal would be created for each property of each header/row/column/cell. To work around this, we can disable reactive properties via table options (name to be decided).

export interface AngularReactivityFlags {
  header: boolean
  column: boolean
  row: boolean
  cell: boolean
  table: boolean
}

interface TableOptions_AngularReactivity {
  reactivity?: Partial<AngularReactivityFlags>
}

  • skipBaseProperties now check via string indexs instead of endsWith/startsWith to improve performance a little when there are many rows
  • Removed enableExperimentalReactivity with a new reactivity object that allows to make reactive properties based on the type of object
  • setReactiveProp will now override with a getter that will create the computed lazily. This may improve performance a bit since previously a computed was created synchronously, while now it is created only once the getter is invoked for the first time
  • BREAKING CHANGE: instead of calling table() to handle the entire table as a signal, you now need to call table.get()

// todo

Still in draft, so there may be changes about this.

FlexRender now relies on ngDoCheck to check if the content is dirty

I introduced a new input (named flexRenderNotifier, note: tbd) that allows to change this behavior. This can be used to run view checks introduced in the previous release only when the state of the table changes, instead of every time angular determine the view is dirty.

Benchmarks

On average, no reactivity takes about 34.11% less time than enabling all reactivity flags

 ✓ tests/benchmarks/injectTable.benchmark.ts (16) 89397ms
   ✓ injectTable - 100 elements (2) 1228ms
     name                 hz     min     max    mean     p75     p99    p995    p999     rme  samples
   · No reactivity    478.95  0.8006  4.7787  2.0879  2.1033  4.4813  4.7538  4.7787  ±2.84%      240   fastest
   · Full reactivity  402.47  1.2451  5.2326  2.4846  2.5394  4.4560  5.1281  5.2326  ±2.44%      202
   ✓ injectTable - 1000 elements (2) 1285ms
     name                  hz      min      max     mean      p75      p99     p995     p999     rme  samples
   · No reactivity    88.1605   9.5865  23.9425  11.3429  11.0828  23.9425  23.9425  23.9425  ±5.55%       45   fastest
   · Full reactivity  59.9771  15.4324  30.0653  16.6730  16.4753  30.0653  30.0653  30.0653  ±5.94%       30
   ✓ injectTable - 2000 elements (2) 1457ms
     name                  hz      min      max     mean      p75      p99     p995     p999      rme  samples
   · No reactivity    43.1559  19.0770  48.5802  23.1718  23.8451  48.5802  48.5802  48.5802  ±12.15%       22   fastest
   · Full reactivity  26.7554  31.2603  61.8903  37.3757  35.1764  61.8903  61.8903  61.8903  ±16.16%       14
   ✓ injectTable - 5000 elements (2) 2069ms
     name                  hz      min      max     mean      p75      p99     p995     p999      rme  samples
   · No reactivity    18.7756  48.8352  80.7604  53.2605  51.9892  80.7604  80.7604  80.7604  ±13.12%       10   fastest
   · Full reactivity  11.4146  78.1029   114.20  87.6068  89.7341   114.20   114.20   114.20  ±16.41%        6
   ✓ injectTable - 10000 elements (2) 3425ms
     name                 hz     min     max    mean     p75     p99    p995    p999      rme  samples
   · No reactivity    9.2817  100.05  131.47  107.74  105.85  131.47  131.47  131.47  ±15.53%        5   fastest
   · Full reactivity  5.8318  160.01  190.27  171.47  175.66  190.27  190.27  190.27   ±8.83%        5
   ✓ injectTable - 25000 elements (2) 9133ms
     name                 hz     min     max    mean     p75     p99    p995    p999      rme  samples
   · No reactivity    3.4413  255.76  329.70  290.59  326.18  329.70  329.70  329.70  ±14.88%        5   fastest
   · Full reactivity  2.1823  417.27  523.97  458.23  483.82  523.97  523.97  523.97  ±12.22%        5
   ✓ injectTable - 50000 elements (2) 24258ms
     name                 hz       min       max      mean       p75       p99      p995      p999      rme  samples
   · No reactivity    1.1524    656.22  1,147.60    867.73  1,027.44  1,147.60  1,147.60  1,147.60  ±31.03%        5   fastest
   · Full reactivity  0.7608  1,052.31  1,654.41  1,314.38  1,434.89  1,654.41  1,654.41  1,654.41  ±22.38%        5
   ✓ injectTable - 100000 elements (2) 46539ms
     name                 hz       min       max      mean       p75       p99      p995      p999     rme  samples
   · No reactivity    0.7196  1,270.23  1,511.27  1,389.61  1,427.98  1,511.27  1,511.27  1,511.27  ±7.95%        5   fastest
   · Full reactivity  0.4286  2,237.14  2,524.88  2,333.38  2,320.52  2,524.88  2,524.88  2,524.88  ±5.98%        5

 BENCH  Summary

  No reactivity - tests/benchmarks/injectTable.benchmark.ts > injectTable - 100 elements
    1.19x faster than Full reactivity

  No reactivity - tests/benchmarks/injectTable.benchmark.ts > injectTable - 1000 elements
    1.47x faster than Full reactivity

  No reactivity - tests/benchmarks/injectTable.benchmark.ts > injectTable - 2000 elements
    1.61x faster than Full reactivity

  No reactivity - tests/benchmarks/injectTable.benchmark.ts > injectTable - 5000 elements
    1.64x faster than Full reactivity

  No reactivity - tests/benchmarks/injectTable.benchmark.ts > injectTable - 10000 elements
    1.59x faster than Full reactivity

  No reactivity - tests/benchmarks/injectTable.benchmark.ts > injectTable - 25000 elements
    1.58x faster than Full reactivity

  No reactivity - tests/benchmarks/injectTable.benchmark.ts > injectTable - 50000 elements
    1.51x faster than Full reactivity

  No reactivity - tests/benchmarks/injectTable.benchmark.ts > injectTable - 100000 elements
    1.68x faster than Full reactivity

@riccardoperra riccardoperra changed the title feat(angular): improvements to angularReactivityFeature, remove proxies feat(angular): improvements to angularReactivityFeature, try to remove proxies Feb 14, 2025
@nx-cloud
Copy link

nx-cloud bot commented Feb 14, 2025

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit e4f6fdf

Command Status Duration Result
nx affected --targets=test:format,test:eslint,t... ❌ Failed 54s View ↗
nx run-many --targets=build -p @tanstack/table-... ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2026-01-06 18:37:23 UTC

@riccardoperra riccardoperra force-pushed the feat/alpha_angular_granular_signal branch from 01cf821 to 961a7df Compare February 14, 2025 23:44
@riccardoperra riccardoperra force-pushed the feat/alpha_angular_granular_signal branch from d226238 to 878e7cc Compare May 17, 2025 12:35
@riccardoperra riccardoperra force-pushed the feat/alpha_angular_granular_signal branch from 878e7cc to b3badb7 Compare January 6, 2026 11:41
@changeset-bot
Copy link

changeset-bot bot commented Jan 6, 2026

⚠️ No Changeset found

Latest commit: e4f6fdf

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link

coderabbitai bot commented Jan 6, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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 and usage tips.

@riccardoperra riccardoperra changed the base branch from alpha to store January 6, 2026 11:42
@riccardoperra riccardoperra marked this pull request as ready for review January 6, 2026 18:31
@riccardoperra riccardoperra merged commit 0852ad9 into store Jan 6, 2026
2 of 4 checks passed
@riccardoperra riccardoperra deleted the feat/alpha_angular_granular_signal branch January 6, 2026 18:36
KevinVandy added a commit that referenced this pull request Jan 8, 2026
* progress on rewriting tanstack table with tanstack store

* poc for new solid table adapter

* fix solid examples

* remove temp

* fix header groups bug

* refactor assignAPIs

* svelte somewhat working

* feat: move row, cell, headers, and column methods to the prototype save tons of memory

* update vue adapter and examples

* more vue stuff

* update angular table kind of

* lit adapter refactor

* fix(angular): update test config and added missing injector context

* injector context is now needed since we use injectStore

* update some unit tests and fix sherif

* fix some more tests - angular focussed

* update experimental virtualized examples

* fix linting and react/preact adapters

* disable all but react and preact and table-core for now

* fix some shadcn issues

* css

* test react/preact example tsc

* fix a lot of react examples

* omg I fixed a tvalue column helper issue!

* add tanstack forma example

* small make state updater type fix even though it might be removed soon

* Use baseStore and derived store to allow external state again

* rename a bunch of examples

* fix example names

* feat(angular): improvements to angularReactivityFeature (#5921)

* fix array types and imports

* toComputed return a named function, add more granular flags

* remove table proxy implementation, improve angular reactivity feature

* wip: add flex render custom notifier when table state change

* ci: apply automated fixes

* wip: angularReactivityFeature replace _rootNotifier with get

* ci: apply automated fixes

* wip: some renames, types improvements and test cases

- rename `_setRootNotifier` to `_setTableNotifier`
- add strict typings to `toComputed`
- add test case for reactivity utils

* ci: apply automated fixes

* wip: fix types, add reactive symbol to detect whether a property is reactive

* wip: setup benchmark test

* wip: skipBaseProperties skip properties that ends with Handler

* wip: skipBaseProperties skip properties that ends with Handler, pass skip custom fn from table options

* align base branch, fix lazy init

* fix table helper types

* cleanup lazy signal initializer

* table reactivity feature cleanup

* flex render cleanup and export FlexRender as directive

* refactor injectTable to work with tanstack store reactivity

* fix injectTable test

* fix test utils test

* refactor reactivity handling in angular features and improve prototype assignments

* fix row-dnd tsconfig

* fix test

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* chore(angular): using signals into flexRender to avoid re-rendering

* feat(angular): flex-render switch to 'tableChange' notifier mode for performance improvements

* feat: createTableHook

* more createTableHook flex render improvements and fixed some tests

* fix other table-core tests

* fix more lint errors in react examples

* fix preact typeconfig issues in examples

* ci: apply automated fixes

* fix knip, disable preact-table publishing for now

---------

Co-authored-by: riccardoperra <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants