Skip to content

Commit 1661fcf

Browse files
fix: renderComponent, add renderSnippet, and some other Svelte fix-ups (#5888)
* update render-compnent and use dynamic component instead of snippet rendering in FlexRender * fix linting error (import order) * added renderSnippet example * move svelte snippet example and update svelte dependencies * update deps * ci: apply automated fixes * add doc for svelte renderSnippet * Fix typo in snippet --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 495f0ed commit 1661fcf

File tree

27 files changed

+2758
-1408
lines changed

27 files changed

+2758
-1408
lines changed

docs/framework/svelte/svelte-table.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,22 @@ Takes an `options` object and returns a table.
3232
A Svelte component for rendering cell/header/footer templates with dynamic values.
3333

3434
FlexRender supports any type of renderable content supported by Svelte:
35+
3536
- Scalar data types such as numbers, strings, etc.
3637
- Svelte components (when wrapped with `renderComponent`)
38+
- Svelte snippets (when wrapped with `renderSnippet`)
3739

3840
Example:
3941

4042
```svelte
4143
<script lang="ts">
42-
import {
44+
import {
4345
type ColumnDef,
4446
FlexRender,
4547
createTable,
4648
getCoreRowModel,
47-
renderComponent
49+
renderComponent,
50+
renderSnippet
4851
} from '@tanstack/svelte-table'
4952
import { StatusTag } from '$lib/components/status-tag.svelte'
5053
import type { Person } from './types'
@@ -60,6 +63,11 @@ Example:
6063
/* Renders a Svelte component */
6164
accessorKey: 'status',
6265
cell: (info) => renderComponent(StatusTag, { value: info.getValue() })
66+
},
67+
{
68+
/* Renders a Svelte component */
69+
accessorKey: 'email',
70+
cell: (info) => renderSnippet(mailtoLink, info.getValue())
6371
}
6472
]
6573
@@ -70,6 +78,12 @@ Example:
7078
})
7179
</script>
7280
81+
{#snippet mailtoLink(email: string)}
82+
<a href="mailto:{email}">
83+
{email}
84+
</a>
85+
{/snippet}
86+
7387
<table>
7488
<tbody>
7589
{#each table.getRowModel().rows as row}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
node_modules
2+
.DS_Store
3+
dist
4+
dist-ssr
5+
*.local
6+
7+
src/**/*.d.ts
8+
src/**/*.map
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: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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.0" />
6+
<title>Vite App</title>
7+
<script type="module" src="https://cdn.skypack.dev/twind/shim"></script>
8+
</head>
9+
10+
<body>
11+
<div id="root"></div>
12+
<script type="module" src="/src/main.ts"></script>
13+
</body>
14+
</html>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "tanstack-table-example-svelte-basic-snippets",
3+
"version": "0.0.0",
4+
"private": true,
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite",
8+
"build": "vite build",
9+
"serve": "vite preview",
10+
"test:types": "svelte-check --tsconfig ./tsconfig.json",
11+
"lint": "eslint ./src"
12+
},
13+
"devDependencies": {
14+
"@rollup/plugin-replace": "^6.0.1",
15+
"@sveltejs/vite-plugin-svelte": "^4.0.4",
16+
"@tanstack/svelte-table": "^9.0.0-alpha.10",
17+
"@tsconfig/svelte": "^5.0.4",
18+
"svelte": "^5.19.3",
19+
"svelte-check": "^4.1.4",
20+
"typescript": "5.6.3",
21+
"vite": "^5.4.11"
22+
}
23+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
<script lang="ts">
2+
import {
3+
createTableHelper,
4+
FlexRender,
5+
renderSnippet,
6+
} from '@tanstack/svelte-table'
7+
import { capitalized, countup, spectrum } from './snippets.svelte'
8+
import './index.css'
9+
10+
/**
11+
* This `svelte-table` example demonstrates the following:
12+
* - Creating a basic table with no additional features (sorting, filtering,
13+
* grouping, etc),
14+
* - Creating and using a `table helper`,
15+
* - Defining columns with custom headers, cells, and footers using the table
16+
* helper, and
17+
* - Rendering a table with the instance APIs.
18+
*/
19+
20+
// 1. Define what the shape of your data will be for each row
21+
type Person = {
22+
firstName: string
23+
lastName: string
24+
age: number
25+
visits: number
26+
status: string
27+
progress: number
28+
}
29+
30+
// 2. Create some dummy data with a stable reference (this could be an API
31+
// response stored in a rune).
32+
const data: Person[] = [
33+
{
34+
firstName: 'tanner',
35+
lastName: 'linsley',
36+
age: 24,
37+
visits: 100,
38+
status: 'In Relationship',
39+
progress: 50,
40+
},
41+
{
42+
firstName: 'tandy',
43+
lastName: 'miller',
44+
age: 40,
45+
visits: 40,
46+
status: 'Single',
47+
progress: 80,
48+
},
49+
{
50+
firstName: 'joe',
51+
lastName: 'dirte',
52+
age: 45,
53+
visits: 20,
54+
status: 'Complicated',
55+
progress: 10,
56+
},
57+
]
58+
59+
// 3. New in V9! Tell the table which features and row models we want to use.
60+
// In this case, this will be a basic table with no additional features
61+
const tableHelper = createTableHelper({
62+
_features: {},
63+
// 3a. `_rowModels` defines client-side row models. `Core` row model is now
64+
// included by default, but you can still override it here.
65+
_rowModels: {},
66+
// 3b. Optionally, set the `TData` type. Omit TData is this table helper
67+
// will be used to create multiple tables with different data types.
68+
TData: {} as Person,
69+
})
70+
71+
// 4. For convenience, destructure the desired utilities from `tableHelper`
72+
const { columnHelper, createTable } = tableHelper
73+
74+
// 5. Define the columns for your table with a stable reference (in this case,
75+
// defined statically).
76+
const columns = columnHelper.columns([
77+
columnHelper.accessor('firstName', {
78+
header: 'First Name',
79+
// 5a. Use the `renderSnippet` utility to render the snippet in the cell.
80+
cell: (info) => renderSnippet(capitalized, info.getValue()),
81+
}),
82+
columnHelper.accessor('lastName', {
83+
header: 'Last Name',
84+
cell: (info) => renderSnippet(capitalized, info.getValue()),
85+
}),
86+
columnHelper.accessor('age', {
87+
header: 'Age',
88+
cell: (info) => renderSnippet(countup, info.getValue()),
89+
}),
90+
columnHelper.accessor('visits', {
91+
header: 'Visits',
92+
cell: (info) => renderSnippet(countup, info.getValue()),
93+
}),
94+
columnHelper.accessor('status', {
95+
header: 'Status',
96+
}),
97+
columnHelper.accessor('progress', {
98+
header: 'Profile Progress',
99+
cell(info) {
100+
return renderSnippet(spectrum, {
101+
value: info.getValue(),
102+
min: 0,
103+
max: 100,
104+
})
105+
},
106+
}),
107+
])
108+
109+
// 6. Create the table instance with columns and data. Features and row
110+
// models are already defined in the `tableHelper` object that
111+
// `createTable` was destructured from.
112+
const table = createTable({
113+
columns,
114+
data,
115+
})
116+
</script>
117+
118+
<!-- 7. Render the table in markup using the Instance APIs. -->
119+
<div class="p-2">
120+
<table>
121+
<thead>
122+
{#each table.getHeaderGroups() as headerGroup}
123+
<tr>
124+
{#each headerGroup.headers as header}
125+
<th>
126+
{#if !header.isPlaceholder}
127+
<FlexRender
128+
content={header.column.columnDef.header}
129+
context={header.getContext()}
130+
/>
131+
{/if}
132+
</th>
133+
{/each}
134+
</tr>
135+
{/each}
136+
</thead>
137+
<tbody>
138+
{#each table.getRowModel().rows as row}
139+
<tr>
140+
{#each row.getAllCells() as cell}
141+
<td>
142+
<FlexRender
143+
content={cell.column.columnDef.cell}
144+
context={cell.getContext()}
145+
/>
146+
</td>
147+
{/each}
148+
</tr>
149+
{/each}
150+
</tbody>
151+
</table>
152+
</div>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
font-weight: normal;
19+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @ts-ignore - Svelte type definitions are not properly recognized
2+
import { mount } from 'svelte'
3+
import App from './App.svelte'
4+
5+
const app = mount(App, {
6+
target: document.getElementById('root')!,
7+
})
8+
9+
export default app
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<script module lang="ts">
2+
import { createRawSnippet } from 'svelte'
3+
4+
export { capitalized, spectrum, countup }
5+
6+
function getColor(value: number, min: number, max: number) {
7+
console.log(value, min, max)
8+
const ratio = (value - min) / (max - min)
9+
console.log(value - min, max - min, ratio)
10+
const hue = Math.floor(120 * ratio) // 0 (red) to 120 (green)
11+
return `hsl(${hue}, 100%, 50%)`
12+
}
13+
14+
type SpectrumParams = {
15+
value: number
16+
min: number
17+
max: number
18+
}
19+
20+
const countup = createRawSnippet<[value: number]>((value) => {
21+
return {
22+
render() {
23+
return `<p>0</p>`
24+
},
25+
setup(element) {
26+
let count = 0
27+
const interval = setInterval(() => {
28+
count++
29+
element.textContent = `${count}`
30+
31+
if (count === value()) {
32+
clearInterval(interval)
33+
}
34+
}, 1000 / value())
35+
36+
return () => {
37+
clearInterval(interval)
38+
}
39+
},
40+
}
41+
})
42+
</script>
43+
44+
{#snippet capitalized(value: string)}
45+
<p class="text-capitalize">{value}</p>
46+
{/snippet}
47+
48+
{#snippet spectrum({ value, min, max }: SpectrumParams)}
49+
<div
50+
class="text-center font-semibold"
51+
style="background-color: {getColor(value, min, max)}"
52+
>
53+
{value}
54+
</div>
55+
{/snippet}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
2+
3+
export default {
4+
preprocess: vitePreprocess(),
5+
}

0 commit comments

Comments
 (0)