changed to svelte headless table for reactive data

This commit is contained in:
John O'Keefe 2024-09-07 19:33:02 -04:00
parent cbcb07d2f1
commit 5915bb28b8
2 changed files with 99 additions and 139 deletions

View File

@ -16,6 +16,7 @@
"postcss": "^8.4.45",
"svelte": "^4.0.0",
"svelte-check": "^3.4.3",
"svelte-headless-table": "^0.18.2",
"svelte-preprocess": "^5.0.3",
"svelte-spa-router": "^4.0.1",
"tailwind-merge": "^2.5.2",
@ -26,9 +27,8 @@
},
"dependencies": {
"@popperjs/core": "^2.11.8",
"@tanstack/svelte-table": "^8.20.5",
"flowbite": "^2.5.1",
"flowbite-svelte": "^0.46.16",
"moment": "^2.30.1"
}
}
}

View File

@ -1,151 +1,111 @@
<script lang="ts">
import {writable} from 'svelte/store'
import type {ColumnDef, TableOptions} from '@tanstack/svelte-table'
import {
createSvelteTable,
flexRender,
getCoreRowModel,
getSortedRowModel,
type OnChangeFn,
type SortingState,
} from '@tanstack/svelte-table'
import {createTable, Render, Subscribe} from "svelte-headless-table";
// @ts-ignore
import { addSortBy } from "svelte-headless-table/plugins";
import {tableItems} from "./GlobalVariablesAndHelperFunctions.svelte"
import type {TableItem, TableItems} from "../helperTypes/TableTypes";
let tableItemsView: TableItems
tableItems.subscribe(value => tableItemsView = value)
//when adding sort here is code { sort: addSortBy() }
const table = createTable(tableItems, { sort: addSortBy() })
const defaultColumns: ColumnDef<TableItem>[] = [
{
accessorKey: 'id',
header: () => "Service Id",
cell: info => info.getValue(),
},
{
accessorKey: 'service',
header: () => 'Service',
cell: info => info.getValue(),
},
{
accessorKey: 'progress',
header: () => 'Episode Progress',
cell: info => info.getValue(),
},
{
accessorKey: 'status',
header: () => 'Status',
cell: info => info.getValue(),
},
{
accessorKey: 'startedAt',
header: () => 'Started At',
cell: info => info.getValue(),
},
{
accessorKey: 'completedAt',
header: () => 'Completed At',
cell: info => info.getValue(),
},
{
accessorKey: 'score',
header: () => 'Rating',
cell: info => info.getValue(),
},
{
accessorKey: 'repeat',
header: () => 'Repeat',
cell: info => info.getValue(),
},
{
accessorKey: 'notes',
header: () => 'Notes',
cell: info => info.getValue(),
},
]
const columns = table.createColumns([
table.column({
header: "Service Id",
accessor: 'id',
}),
table.column({
header: 'Service',
accessor: 'service',
}),
table.column({
header: 'Episode Progress',
accessor: 'progress',
}),
table.column({
header: 'Status',
accessor: 'status',
}),
table.column({
header: 'Started At',
accessor: 'startedAt',
}),
table.column({
header: 'Completed At',
accessor: 'completedAt',
}),
table.column({
header: 'Rating',
accessor: 'score',
}),
table.column({
header: 'Repeat',
accessor: 'repeat',
}),
table.column({
header: 'Notes',
accessor: 'notes',
}),
])
let sorting: SortingState = []
const setSorting: OnChangeFn<SortingState> = updater => {
if (updater instanceof Function) {
sorting = updater(sorting)
} else {
sorting = updater
}
options.update(old => ({
...old,
state: {
...old.state,
sorting,
},
}))
}
const options = writable<TableOptions<TableItem>>({
data: tableItemsView,
columns: defaultColumns,
state: {
sorting,
},
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
})
const rerender = () => {
console.log(tableItemsView)
options.update(options => ({
...options,
data: tableItemsView,
}))
}
const table = createSvelteTable(options)
//add pluginStates when add sort back
const {
headerRows,
rows,
tableAttrs,
tableBodyAttrs,
} = table.createViewModel(columns)
</script>
<div class="relative overflow-x-auto rounded-lg mb-5">
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
{#each $table.getHeaderGroups() as headerGroup}
<tr>
{#each headerGroup.headers as header}
<th class="px-6 py-3">
{#if !header.isPlaceholder}
<button
class:cursor-pointer={header.column.getCanSort()}
class:select-none={header.column.getCanSort()}
on:click={header.column.getToggleSortingHandler()}
<table
class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400"
{...$tableAttrs}
>
<thead
class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400"
>
{#each $headerRows as headerRow (headerRow.id)}
<Subscribe attrs={headerRow.attrs()} let:attrs>
<tr {...attrs}>
{#each headerRow.cells as cell (cell.id)}
<Subscribe attrs={cell.attrs()} let:attrs props={cell.props()} let:props>
<th
{...attrs}
on:click={props.sort.toggle}
class:sorted={props.sort.order !== undefined}
class="px-6 py-3"
>
<svelte:component
this={flexRender(
header.column.columnDef.header,
header.getContext()
)}
/>
{#if header.column.getIsSorted().toString() === 'asc'}
🔼
{:else if header.column.getIsSorted().toString() === 'desc'}
🔽
{/if}
</button>
{/if}
</th>
{/each}
</tr>
<div>
<Render of={cell.render()}/>
{#if props.sort.order === 'asc'}
⬇️
{:else if props.sort.order === 'desc'}
⬆️
{/if}
</div>
</th>
</Subscribe>
{/each}
</tr>
</Subscribe>
{/each}
</thead>
<tbody>
{#each $table.getRowModel().rows as row}
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
{#each row.getVisibleCells() as cell}
<td class="px-6 py-4">
<svelte:component
this={flexRender(cell.column.columnDef.cell, cell.getContext())}
/>
</td>
{/each}
</tr>
{/each}
<tbody {...$tableBodyAttrs}>
{#each $rows as row (row.id)}
<Subscribe attrs={row.attrs()} let:attrs>
<tr
{...attrs}
class="bg-white border-b dark:bg-gray-800 dark:border-gray-700"
>
{#each row.cells as cell (cell.id)}
<Subscribe attrs={cell.attrs()} let:attrs>
<td {...attrs} class="px-6 py-4">
<Render of={cell.render()}/>
</td>
</Subscribe>
{/each}
</tr>
</Subscribe>
{/each}
</tbody>
</table>
<button on:click={() => rerender()} class="border p-2 mb-3"> Rerender</button>
</div>