@@ -9,7 +9,7 @@ TanStack Table Vue is a wrapper library that simplifies using TanStack Table (fo
99- ✅ ** No JSX Required** - Define columns with plain objects, not render functions
1010- ✅ ** Vue Idiomatic** - Uses scoped slots and Vue template syntax
1111- ✅ ** Type-Safe** - Full TypeScript support with generics
12- - ✅ ** Flexible** - Supports all TanStack Table features
12+ - ✅ ** Flexible** - Supports all TanStack Table features including sorting, grouping, and more
1313- ✅ ** Simple API** - Easy to understand and use
1414- ✅ ** Lightweight** - Minimal abstraction over TanStack Table
1515
@@ -33,50 +33,86 @@ bun add tanstack-table-vue @tanstack/vue-table
3333
3434``` vue
3535<script setup lang="ts">
36- import { TSTable, defineColumns } from 'tanstack-table-vue'
36+ import { TSTable } from 'tanstack-table-vue'
37+ import { createColumnHelper, getCoreRowModel, getSortedRowModel } from '@tanstack/vue-table'
3738
3839interface Person {
3940 firstName: string
4041 lastName: string
4142 age: number
43+ visits: number
44+ status: string
45+ progress: number
4246}
4347
4448const data: Person[] = [
45- { firstName: 'John', lastName: 'Doe', age: 30 },
46- { firstName: 'Jane', lastName: 'Smith', age: 25 },
47- ]
48-
49- const columns = defineColumns<Person>([
5049 {
51- id: 'firstName',
52- header: 'First Name',
50+ firstName: 'tanner',
51+ lastName: 'linsley',
52+ age: 24,
53+ visits: 100,
54+ status: 'In Relationship',
55+ progress: 50,
5356 },
5457 {
55- id: 'lastName',
56- header: 'Last Name',
57- },
58- {
59- id: 'age',
60- header: 'Age',
61- },
62- {
63- id: 'actions',
64- header: 'Actions',
58+ firstName: 'tandy',
59+ lastName: 'miller',
60+ age: 40,
61+ visits: 40,
62+ status: 'Single',
63+ progress: 80,
6564 },
6665]
66+
67+ const columnHelper = createColumnHelper<Person>()
68+
69+ const columns = [
70+ columnHelper.group({
71+ id: 'name',
72+ header: 'Name',
73+ columns: [columnHelper.accessor('firstName', {}), columnHelper.accessor('lastName', {})],
74+ }),
75+ columnHelper.group({
76+ id: 'info',
77+ header: 'Info',
78+ columns: [
79+ columnHelper.accessor('age', {}),
80+ columnHelper.group({
81+ id: 'moreInfo',
82+ header: 'More Info',
83+ columns: [
84+ columnHelper.accessor('visits', {}),
85+ columnHelper.accessor('status', {}),
86+ columnHelper.accessor('progress', {}),
87+ ],
88+ }),
89+ ],
90+ }),
91+ ]
92+
93+ const tableOptions = {
94+ getSortedRowModel: getSortedRowModel(),
95+ getCoreRowModel: getCoreRowModel(),
96+ }
6797</script>
6898
6999<template>
70- <TSTable :data="data" :columns="columns">
71- <!-- Custom cell rendering with scoped slots -->
72- <template #cell-age="{ value }">
73- <span :class="value > 25 ? 'text-red' : 'text-green'"> {{ value }} years old </span>
100+ <TSTable :columns="columns" :data="data" :tableOptions="tableOptions">
101+ <!-- Custom header rendering with sorting -->
102+ <template #header-firstName="{ column }">
103+ <div class="flex items-center cursor-pointer" @click="column.toggleSorting()">
104+ <span class="font-bold">First Name</span>
105+ <span v-if="column.getIsSorted() === 'desc'">🔽</span>
106+ <span v-else-if="column.getIsSorted() === 'asc'">🔼</span>
107+ <span v-else>⏺️</span>
108+ </div>
74109 </template>
75110
76- <!-- Actions column with custom rendering -->
77- <template #cell-actions="{ row }">
78- <button @click="editPerson(row.original)">Edit</button>
79- <button @click="deletePerson(row.original)">Delete</button>
111+ <!-- Custom cell rendering -->
112+ <template #cell-status="{ value }">
113+ <span class="px-2 py-1 rounded text-xs font-medium" :class="getStatusClass(value)">
114+ {{ value }}
115+ </span>
80116 </template>
81117 </TSTable>
82118</template>
@@ -86,46 +122,35 @@ const columns = defineColumns<Person>([
86122
87123Customize your table with these scoped slots:
88124
89- - ` #cell-{columnId}="{ value, row, info }" ` - Custom cell rendering
90- - ` #header-{columnId}="{ header }" ` - Custom header rendering
91- - ` #footer-{columnId}="{ footer }" ` - Custom footer rendering
125+ - ` #cell-{columnId}="{ value, row, cell }" ` - Custom cell rendering
126+ - ` #header-{columnId}="{ column, header }" ` - Custom header rendering with sorting support
127+ - ` #footer-{columnId}="{ column, footer }" ` - Custom footer rendering
128+
129+ ## 🔄 Column Definition
92130
93- ## 🔄 Migration from JSX
131+ The library supports two ways to define columns:
94132
95- Before :
133+ 1 . Using ` columnHelper.accessor ` :
96134
97135``` typescript
98- // Using JSX and render functions
99- columnHelper .accessor (' firstName' , {
100- header : () => <span >First Name < / span > ,
101- cell : (info ) =>
102- h (CustomComponent , {
103- props: {
104- value: info .getValue (),
105- },
106- }),
107- footer : (props ) => props .column .id ,
136+ // Simple accessor
137+ columnHelper .accessor (' firstName' , {})
138+
139+ // With group
140+ columnHelper .group ({
141+ id: ' name' ,
142+ header: ' Name' ,
143+ columns: [columnHelper .accessor (' firstName' , {}), columnHelper .accessor (' lastName' , {})],
108144})
109145```
110146
111- After :
147+ 2 . Using ` columnHelper.display ` for custom columns :
112148
113149``` typescript
114- // Using plain objects
115- {
116- id : ' firstName' ,
117- }
118-
119- // And in your template
120- < template #header - firstName >
121- <span >First Name < / span >
122- < / template >
123- < template #cell - firstName = " { value }" >
124- <CustomComponent >{{ value }}< / CustomComponent >
125- < / template >
126- < template #footer - firstName = " { column }" >
127- <span >{{ column .id }}< / span >
128- < / template >
150+ columnHelper .display ({
151+ id: ' actions' ,
152+ cell : () => ' Actions' ,
153+ })
129154```
130155
131156## 🤝 Contributing
0 commit comments