Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 13 additions & 6 deletions examples/basic/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<script setup lang="ts">
import { TSTable } from 'tanstack-table-vue'
import { createColumnHelper, FlexRender, getCoreRowModel, getSortedRowModel, type Column } from '@tanstack/vue-table'
import { TSTable, type TableOptions } from 'tanstack-table-vue'
import { createColumnHelper, FlexRender, getSortedRowModel, type Column } from '@tanstack/vue-table'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from './components/ui/table'
import { useQuery } from '@tanstack/vue-query'
import { computed } from 'vue'


interface Person {
Expand Down Expand Up @@ -49,6 +50,13 @@ const { data, isLoading } = useQuery({
},
})

const persons = computed(() => {
if (data.value) {
return data.value
}
return []
})

function getSortIcon(column: Column<Person>) {
if (!column.getCanSort?.()) return null

Expand Down Expand Up @@ -90,7 +98,7 @@ const columns = [
columns: [
columnHelper.group({
id: 'moreInfo',
header: 'More Info',
header: 'More Info ',
columns: [
columnHelper.accessor('visits', {}),
columnHelper.accessor('status', {}),
Expand All @@ -105,16 +113,15 @@ const columns = [
})
]

const tableOptions = {
const tableOptions: TableOptions = {
getSortedRowModel: getSortedRowModel(),
getCoreRowModel: getCoreRowModel(),
}
</script>

<template>
<div class="container mx-auto p-4">
<h1 class="text-2xl font-bold mb-4">TSTable with Slots Example</h1>
<TSTable :columns="columns" :data="defaultData" :tableOptions="tableOptions">
<TSTable :columns="columns" :data="persons" :tableOptions="tableOptions">

<template #header-firstName="{ column }">
<div class="flex items-center cursor-pointer" @click="column.toggleSorting()">
Expand Down
41 changes: 28 additions & 13 deletions packages/core/src/components/TSTable.vue
Original file line number Diff line number Diff line change
@@ -1,42 +1,57 @@
<script lang="ts">
import type { ColumnDef, RowData, Table } from '@tanstack/vue-table'
import type { ColumnDef, RowData, Table, TableOptionsWithReactiveData } from '@tanstack/vue-table'
import type { CellSlotProps, FooterSlotProps, HeaderSlotProps } from '../shared/types'

export type TableOptions = Omit<TableOptionsWithReactiveData<any>, 'columns' | 'data' | 'getCoreRowModel'>

export interface TSTableProps<TData extends RowData & object> {
columns: ColumnDef<TData, any>[]
data: TData[]
tableOptions?: Record<string, any>
tableOptions?: TableOptions
}
</script>

<script setup lang="ts" generic="TData extends RowData & object">
import { computed, useSlots } from 'vue'
import { useVueTable, createColumnHelper, type ColumnDef as TStackColumnDef, getCoreRowModel } from '@tanstack/vue-table'
import { computed, useSlots, watch } from 'vue'
import { useVueTable, createColumnHelper, getCoreRowModel } from '@tanstack/vue-table'
import { processColumns } from '../shared'

const props = defineProps<TSTableProps<TData>>()

const slots = useSlots()
const columnHelper = createColumnHelper<TData>()

// Use memo pattern for expensive column processing
const processedColumns = computed(() => {
const initialTable = useVueTable<TData>({
columns: props.columns as TStackColumnDef<TData, any>[],
data: props.data,
getCoreRowModel: getCoreRowModel(),
...props.tableOptions
})
return processColumns(columnHelper, props.columns, slots, initialTable)
return processColumns(columnHelper, props.columns, slots)
})

const tableOptions = {
// Create initial table options
const initialTableOptions = {
columns: processedColumns.value,
data: props.data,
getCoreRowModel: getCoreRowModel(),
...props.tableOptions
}

const table = useVueTable<TData>(tableOptions)
// Initialize table with initial options
const table = useVueTable<TData>(initialTableOptions)

// Watch for data changes and update table efficiently
watch(() => props.data, (newData) => {
table.setOptions((old) => ({
...old,
data: newData,
}))
}, { flush: 'sync' })

// Watch columns separately to avoid unnecessary recalculations
watch(processedColumns, (newColumns) => {
table.setOptions((old) => ({
...old,
columns: newColumns,
}))
}, { flush: 'sync' })

defineSlots<{
default: (props: {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { default as TSTable, type TSTableProps } from './TSTable.vue'
export { default as TSTable, type TSTableProps, type TableOptions } from './TSTable.vue'
4 changes: 1 addition & 3 deletions packages/core/src/shared/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type {
CellContext,
RowData,
ColumnDef as TStackColumnDef,
Table,
ColumnDef,
} from '@tanstack/vue-table'
import type { Slots } from 'vue'
Expand Down Expand Up @@ -88,7 +87,6 @@ export const processColumns = <TData extends RowData & object>(
columnHelper: ColumnHelper<TData>,
columns: ColumnDef<TData, any>[],
slots: Readonly<Slots>,
table: Table<TData>,
): TStackColumnDef<TData, any>[] => {
return columns.map((col): TStackColumnDef<TData, any> => {
// Handle group columns by checking if columns property exists
Expand All @@ -97,7 +95,7 @@ export const processColumns = <TData extends RowData & object>(
id: col.id || String(Math.random()),
header: (context: HeaderContext<TData, any>) => getHeader(col, slots, context),
footer: col.footer ? (context: HeaderContext<TData, any>) => getFooter(col, slots, context) : undefined,
columns: processColumns(columnHelper, col.columns as ColumnDef<TData, any>[], slots, table),
columns: processColumns(columnHelper, col.columns as ColumnDef<TData, any>[], slots),
meta: col.meta,
})
}
Expand Down