Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8b4d12e
feat(angular): wip add table context and hook helpers
riccardoperra Jan 8, 2026
6e77de3
ci: apply automated fixes
autofix-ci[bot] Jan 8, 2026
8a51b52
update composable table example
riccardoperra Jan 8, 2026
2df745b
add some directives to provide table context
riccardoperra Jan 8, 2026
c085061
remove lazyInit set property workaround
riccardoperra Jan 8, 2026
1b4508b
ci: apply automated fixes
autofix-ci[bot] Jan 8, 2026
2dd1df3
fix garbage collection issues in angular
riccardoperra Jan 9, 2026
fe87811
fix: avoid creating computed cache for methods that need an object as…
riccardoperra Jan 9, 2026
7bd52bc
refactor toComputed, add some tests
riccardoperra Jan 10, 2026
48c70bd
refactor(injectTable): improve type definitions and enhance reactivit…
riccardoperra Jan 10, 2026
80ccaf5
refactor(reactivity): enhance memoization and improve reactivity checks
riccardoperra Jan 10, 2026
8c8bf84
add table cell contexts
riccardoperra Jan 11, 2026
9c92b40
cleanup
riccardoperra Jan 11, 2026
a024ecc
fixes some examples
riccardoperra Jan 11, 2026
a488757
refactor flexRender to work with signals
riccardoperra Jan 11, 2026
022aab1
refactor flexRender implementation to work with signals, add FlexRend…
riccardoperra Jan 11, 2026
96d9286
cleanup examples
riccardoperra Jan 11, 2026
87128f8
cleanup structure
riccardoperra Jan 11, 2026
6fb4bac
table state selector fix for angular
riccardoperra Jan 11, 2026
9591572
basic app table example
riccardoperra Jan 11, 2026
bc95e00
code review fixes
riccardoperra Jan 11, 2026
6002827
flex render run content(props) in injection context
riccardoperra Jan 12, 2026
173db1d
createTableHook add typed helpers
riccardoperra Jan 12, 2026
30c57f4
refactor composable table examples with products/users table componen…
riccardoperra Jan 12, 2026
9d782a8
ci: apply automated fixes
autofix-ci[bot] Jan 12, 2026
e6315c3
refactor table components to use inject functions and update document…
riccardoperra Jan 12, 2026
6c19850
ci: apply automated fixes
autofix-ci[bot] Jan 12, 2026
43014d5
fix: update comment to reflect usage of injectTable hook in app.compo…
riccardoperra Jan 12, 2026
670de06
fix: update documentation for injectFlexRenderCellContext to clarify …
riccardoperra Jan 12, 2026
92f0d47
fix: update RowActionsCell to use typed injectTableCellContext with P…
riccardoperra Jan 12, 2026
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "Node.js",
"image": "mcr.microsoft.com/devcontainers/javascript-node:18"
}
16 changes: 16 additions & 0 deletions examples/angular/basic-app-table/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Editor configuration, see https://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.ts]
quote_type = single

[*.md]
max_line_length = off
trim_trailing_whitespace = false
42 changes: 42 additions & 0 deletions examples/angular/basic-app-table/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.

# Compiled output
/dist
/tmp
/out-tsc
/bazel-out

# Node
/node_modules
npm-debug.log
yarn-error.log

# IDEs and editors
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*

# Miscellaneous
/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings

# System files
.DS_Store
Thumbs.db
27 changes: 27 additions & 0 deletions examples/angular/basic-app-table/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Basic

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.1.2.

## Development server

Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.

## Code scaffolding

Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.

## Build

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.

## Running unit tests

Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).

## Running end-to-end tests

Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.

## Further help

To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
107 changes: 107 additions & 0 deletions examples/angular/basic-app-table/angular.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"basic-app-table": {
"cli": {
"cache": {
"enabled": false
}
},
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"inlineTemplate": true,
"inlineStyle": true,
"skipTests": true,
"style": "scss"
},
"@schematics/angular:class": {
"skipTests": true
},
"@schematics/angular:directive": {
"skipTests": true
},
"@schematics/angular:guard": {
"skipTests": true
},
"@schematics/angular:interceptor": {
"skipTests": true
},
"@schematics/angular:pipe": {
"skipTests": true
},
"@schematics/angular:resolver": {
"skipTests": true
},
"@schematics/angular:service": {
"skipTests": true
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular/build:application",
"options": {
"outputPath": "dist/basic-app-table",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss",
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.scss"],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular/build:dev-server",
"configurations": {
"production": {
"buildTarget": "basic-app-table:build:production"
},
"development": {
"buildTarget": "basic-app-table:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular/build:extract-i18n",
"options": {
"buildTarget": "basic-app-table:build"
}
}
}
}
},
"cli": {
"analytics": false
}
}
34 changes: 34 additions & 0 deletions examples/angular/basic-app-table/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "tanstack-table-example-angular-basic",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"lint": "eslint ./src"
},
"private": true,
"dependencies": {
"@angular/common": "^21.0.6",
"@angular/compiler": "^21.0.6",
"@angular/core": "^21.0.6",
"@angular/forms": "^21.0.6",
"@angular/platform-browser": "^21.0.6",
"@angular/platform-browser-dynamic": "^21.0.6",
"@angular/router": "^21.0.6",
"@tanstack/angular-table": "^9.0.0-alpha.10",
"rxjs": "~7.8.2",
"zone.js": "~0.16.0"
},
"devDependencies": {
"@angular/build": "^21.0.4",
"@angular/cli": "^21.0.4",
"@angular/compiler-cli": "^21.0.6",
"@types/jasmine": "~5.1.13",
"jasmine-core": "~5.13.0",
"tslib": "^2.8.1",
"typescript": "5.9.3"
}
}
42 changes: 42 additions & 0 deletions examples/angular/basic-app-table/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<div class="p-2">
<table>
<thead>
@for (headerGroup of table.getHeaderGroups(); track headerGroup.id) {
<tr>
@for (header of headerGroup.headers; track header.id) {
@if (!header.isPlaceholder) {
<th *flexRenderHeader="header; let header">
<div [innerHTML]="header"></div>
</th>
}
}
</tr>
}
</thead>
<tbody>
@for (row of table.getRowModel().rows; track row.id) {
<tr>
@for (cell of row.getAllCells(); track cell.id) {
<td *flexRenderCell="cell; let cell">
<div [innerHTML]="cell"></div>
</td>
}
</tr>
}
</tbody>
<tfoot>
@for (footerGroup of table.getFooterGroups(); track footerGroup.id) {
<tr>
@for (footer of footerGroup.headers; track footer.id) {
<th *flexRenderFooter="footer; let footer">
{{ footer }}
</th>
}
</tr>
}
</tfoot>
</table>

<div class="h-4"></div>
<button (click)="rerender()" class="border p-2">Rerender</button>
</div>
119 changes: 119 additions & 0 deletions examples/angular/basic-app-table/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { ChangeDetectionStrategy, Component, signal } from '@angular/core'
import { FlexRender, createTableHook } from '@tanstack/angular-table'

// This example uses the new `createTableHook` method to create a re-usable table hook factory instead of independently
// using the standalone `useTable` hook and `createColumnHelper` method. You can choose to use either way.

// 1. Define what the shape of your data will be for each row
type Person = {
firstName: string
lastName: string
age: number
visits: number
status: string
progress: number
}

// 2. Create some dummy data with a stable reference (this could be an API response stored in useState or similar)
const defaultData: Array<Person> = [
{
firstName: 'tanner',
lastName: 'linsley',
age: 24,
visits: 100,
status: 'In Relationship',
progress: 50,
},
{
firstName: 'tandy',
lastName: 'miller',
age: 40,
visits: 40,
status: 'Single',
progress: 80,
},
{
firstName: 'joe',
lastName: 'dirte',
age: 45,
visits: 20,
status: 'Complicated',
progress: 10,
},
{
firstName: 'kevin',
lastName: 'vandy',
age: 28,
visits: 100,
status: 'Single',
progress: 70,
},
]

// 3. New in V9! Tell the table which features and row models we want to use.
// In this case, this will be a basic table with no additional features
const { injectAppTable, createAppColumnHelper } = createTableHook({
_features: {},
_rowModels: {}, // client-side row models. `Core` row model is now included by default, but you can still override it here
debugTable: true,
})

// 4. Create a helper object to help define our columns
const columnHelper = createAppColumnHelper<Person>()

// 5. Define the columns for your table with a stable reference (in this case, defined statically outside of a react component)
const columns = columnHelper.columns([
// accessorKey method (most common for simple use-cases)
columnHelper.accessor('firstName', {
cell: (info) => info.getValue(),
footer: (info) => info.column.id,
}),
// accessorFn used (alternative) along with a custom id
columnHelper.accessor((row) => row.lastName, {
id: 'lastName',
cell: (info) => `<i>${info.getValue()}</i>`,
header: () => `<span>Last Name</span>`,
footer: (info) => info.column.id,
}),
// accessorFn used to transform the data
columnHelper.accessor((row) => Number(row.age), {
id: 'age',
header: () => 'Age',
cell: (info) => info.renderValue(),
footer: (info) => info.column.id,
}),
columnHelper.accessor('visits', {
header: () => `<span>Visits</span>`,
footer: (info) => info.column.id,
}),
columnHelper.accessor('status', {
header: 'Status',
footer: (info) => info.column.id,
}),
columnHelper.accessor('progress', {
header: 'Profile Progress',
footer: (info) => info.column.id,
}),
])

@Component({
selector: 'app-root',
imports: [FlexRender],
templateUrl: './app.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
readonly data = signal<Array<Person>>(defaultData)

// 6. Create the table instance with the required columns and data.
// Features and row models are already defined in the createTableHook call above
readonly table = injectAppTable(() => ({
columns,
data: this.data(),
// add additional table options here or in the createTableHook call above
}))

rerender() {
this.data.set([...defaultData.sort(() => -1)])
}
}
Loading
Loading