Skip to content

Commit 5e15ca3

Browse files
committed
feat(solid): createTableHook helper
Add new examples: - basic app table - composble tables Update config.json to render new solid table examples
1 parent 8c1f418 commit 5e15ca3

26 files changed

Lines changed: 1821 additions & 242 deletions

docs/config.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,7 @@
823823
"label": "solid",
824824
"children": [
825825
{ "to": "framework/solid/examples/basic", "label": "Basic" },
826+
{ "to": "framework/solid/examples/basic-app-table", "label": "Basic (useAppTable)" },
826827
{ "to": "framework/solid/examples/basic-table-helper", "label": "Basic with Helpers" },
827828
{ "to": "framework/solid/examples/column-groups", "label": "Header Groups" }
828829
]
@@ -999,8 +1000,8 @@
9991000
{
10001001
"label": "solid",
10011002
"children": [
1002-
{ "to": "framework/solid/examples/bootstrap", "label": "Solid Bootstrap" }
1003-
]
1003+
{ "to": "framework/solid/examples/bootstrap", "label": "Solid Bootstrap" },
1004+
{ "to": "framework/solid/examples/composable-tables", "label": "Composable Tables" }]
10041005
},
10051006
{
10061007
"label": "vue",
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
dist
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Example
2+
3+
To run this example:
4+
5+
- `npm install` or `yarn`
6+
- `npm run start` or `yarn start`
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<meta name="theme-color" content="#000000" />
7+
<link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.ico" />
8+
<title>Solid App</title>
9+
</head>
10+
<body>
11+
<noscript>You need to enable JavaScript to run this app.</noscript>
12+
<div id="root"></div>
13+
14+
<script src="/src/index.tsx" type="module"></script>
15+
</body>
16+
</html>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "tanstack-table-example-solid-basic-app-table",
3+
"version": "0.0.0",
4+
"description": "",
5+
"scripts": {
6+
"start": "vite",
7+
"dev": "vite",
8+
"build": "vite build",
9+
"serve": "vite preview",
10+
"lint": "eslint ./src"
11+
},
12+
"license": "MIT",
13+
"devDependencies": {
14+
"typescript": "5.9.3",
15+
"vite": "^7.3.1",
16+
"vite-plugin-solid": "^2.11.10"
17+
},
18+
"dependencies": {
19+
"@tanstack/solid-table": "^9.0.0-alpha.10",
20+
"solid-js": "^1.9.11"
21+
}
22+
}
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import { createTableHook } from '@tanstack/solid-table'
2+
import { For, createSignal } from 'solid-js'
3+
4+
// 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.
5+
6+
// 1. Define what the shape of your data will be for each row
7+
type Person = {
8+
firstName: string
9+
lastName: string
10+
age: number
11+
visits: number
12+
status: string
13+
progress: number
14+
}
15+
16+
// 2. Create some dummy data with a stable reference (this could be an API response stored in useState or similar)
17+
const defaultData: Array<Person> = [
18+
{
19+
firstName: 'tanner',
20+
lastName: 'linsley',
21+
age: 24,
22+
visits: 100,
23+
status: 'In Relationship',
24+
progress: 50,
25+
},
26+
{
27+
firstName: 'tandy',
28+
lastName: 'miller',
29+
age: 40,
30+
visits: 40,
31+
status: 'Single',
32+
progress: 80,
33+
},
34+
{
35+
firstName: 'joe',
36+
lastName: 'dirte',
37+
age: 45,
38+
visits: 20,
39+
status: 'Complicated',
40+
progress: 10,
41+
},
42+
{
43+
firstName: 'kevin',
44+
lastName: 'vandy',
45+
age: 28,
46+
visits: 100,
47+
status: 'Single',
48+
progress: 70,
49+
},
50+
]
51+
52+
// 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
53+
const { createAppTable, createAppColumnHelper } = createTableHook({
54+
_features: {},
55+
_rowModels: {}, // client-side row models. `Core` row model is now included by default, but you can still override it here
56+
debugTable: true,
57+
})
58+
59+
// 4. Create a helper object to help define our columns
60+
const columnHelper = createAppColumnHelper<Person>()
61+
62+
// 5. Define the columns for your table with a stable reference (in this case, defined statically outside of a react component)
63+
const columns = columnHelper.columns([
64+
// accessorKey method (most common for simple use-cases)
65+
columnHelper.accessor('firstName', {
66+
cell: (info) => info.getValue(),
67+
footer: (info) => info.column.id,
68+
}),
69+
// accessorFn used (alternative) along with a custom id
70+
columnHelper.accessor((row) => row.lastName, {
71+
id: 'lastName',
72+
cell: (info) => <i>{info.getValue()}</i>,
73+
header: () => <span>Last Name</span>,
74+
footer: (info) => info.column.id,
75+
}),
76+
// accessorFn used to transform the data
77+
columnHelper.accessor((row) => Number(row.age), {
78+
id: 'age',
79+
header: () => 'Age',
80+
cell: (info) => info.renderValue(),
81+
footer: (info) => info.column.id,
82+
}),
83+
columnHelper.accessor('visits', {
84+
header: () => <span>Visits</span>,
85+
footer: (info) => info.column.id,
86+
}),
87+
columnHelper.accessor('status', {
88+
header: 'Status',
89+
footer: (info) => info.column.id,
90+
}),
91+
columnHelper.accessor('progress', {
92+
header: 'Profile Progress',
93+
footer: (info) => info.column.id,
94+
}),
95+
])
96+
97+
export function App() {
98+
// 6. Store data with a stable reference
99+
const [data, setData] = createSignal([...defaultData])
100+
101+
// Helper to rerender with sorted data (by age ascending)
102+
function rerender() {
103+
setData((prev) =>
104+
prev.slice().sort((a: Person, b: Person) => a.age - b.age),
105+
)
106+
}
107+
108+
// 7. Create the table instance with the required columns and data.
109+
// Features and row models are already defined in the createTableHook call above
110+
const table = createAppTable({
111+
columns,
112+
get data() {
113+
return data()
114+
},
115+
// add additional table options here or in the createTableHook call above
116+
})
117+
118+
// 8. Render your table markup from the table instance APIs
119+
return (
120+
<div class="p-2">
121+
<table>
122+
<thead>
123+
<For each={table.getHeaderGroups()}>
124+
{(headerGroup) => (
125+
<tr>
126+
<For each={headerGroup.headers}>
127+
{(header) => (
128+
<th>
129+
<table.FlexRender header={header} />
130+
</th>
131+
)}
132+
</For>
133+
</tr>
134+
)}
135+
</For>
136+
</thead>
137+
<tbody>
138+
<For each={table.getRowModel().rows}>
139+
{(row) => (
140+
<tr>
141+
<For each={row.getAllCells()}>
142+
{(cell) => (
143+
<td>
144+
<table.FlexRender cell={cell} />
145+
</td>
146+
)}
147+
</For>
148+
</tr>
149+
)}
150+
</For>
151+
</tbody>
152+
<tfoot>
153+
<For each={table.getFooterGroups()}>
154+
{(footerGroup) => (
155+
<tr>
156+
<For each={footerGroup.headers}>
157+
{(header) => (
158+
<th>
159+
<table.FlexRender footer={header} />
160+
</th>
161+
)}
162+
</For>
163+
</tr>
164+
)}
165+
</For>
166+
</tfoot>
167+
</table>
168+
<div class="h-4" />
169+
<button onClick={rerender} class="border p-2">
170+
Rerender (sort by age)
171+
</button>
172+
</div>
173+
)
174+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
html {
2+
font-family: sans-serif;
3+
font-size: 14px;
4+
}
5+
6+
table {
7+
border: 1px solid lightgray;
8+
}
9+
10+
tbody {
11+
border-bottom: 1px solid lightgray;
12+
}
13+
14+
th {
15+
border-bottom: 1px solid lightgray;
16+
border-right: 1px solid lightgray;
17+
padding: 2px 4px;
18+
}
19+
20+
tfoot {
21+
color: gray;
22+
}
23+
24+
tfoot th {
25+
font-weight: normal;
26+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { render } from 'solid-js/web'
2+
import './index.css'
3+
import { App } from './App'
4+
5+
render(() => <App />, document.getElementById('root') as HTMLElement)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"useDefineForClassFields": true,
5+
"module": "ESNext",
6+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
7+
"skipLibCheck": true,
8+
9+
/* Bundler mode */
10+
"moduleResolution": "bundler",
11+
"allowImportingTsExtensions": true,
12+
"resolveJsonModule": true,
13+
"isolatedModules": true,
14+
"noEmit": true,
15+
"jsx": "preserve",
16+
"jsxImportSource": "solid-js",
17+
18+
/* Linting */
19+
"strict": true,
20+
"noUnusedLocals": true,
21+
"noUnusedParameters": true,
22+
"noFallthroughCasesInSwitch": true
23+
},
24+
"include": ["src"]
25+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { defineConfig } from 'vite'
2+
import solidPlugin from 'vite-plugin-solid'
3+
4+
export default defineConfig({
5+
plugins: [solidPlugin()],
6+
build: {
7+
target: 'esnext',
8+
polyfillDynamicImport: false,
9+
},
10+
})

0 commit comments

Comments
 (0)