changed to svelte headless table for reactive data
This commit is contained in:
		@@ -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,7 +27,6 @@
 | 
			
		||||
  },
 | 
			
		||||
  "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"
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user