bryanmylee / svelte-headless-table

Unopinionated and extensible data tables for Svelte
https://svelte-headless-table.bryanmylee.com/
487 stars 34 forks source link

createRender onClick not updating with new data #192

Closed hhdhwuus closed 8 months ago

hhdhwuus commented 8 months ago

I have a column where I use createRender to create a button from shadcn-svelte. When the data is updated the click event handler uses stale data from before the update, even though the button's slot (visual representation) correctly shows updated data.

Here is my code for the column:

table.column({
    accessor: (station) => station,
    header: '',
    cell: ({ value }) => {
        return createRender(Button, {[...]})
            .on('click', () => {
                someFunction(value);
                someOtherFunction(value.id);
            })
            .slot(value.id);
    },
    plugins: {
        sort: {
            disable: true
        }
    }
})

I don't know if the issue is with my approach or with the table library.

bryanmylee commented 8 months ago

Unfortunately createRender isn't reactive. When you run it, the value of value is fixed to its initial value.

If you need reactivity, you need to pass a store.

edgarsbarajas commented 3 months ago

Any fixes to this? I'm encountering a similar situation

Forthtilliath commented 2 weeks ago

I needed that today, here my solution :

this.table.column({
    id: 'actions',
    accessor: ({ id, registered, firstname, lastname }) => ({
     id,
    registered,
    name: `${firstname} ${lastname}` as const
    }),
    header: 'Actions',
    cell: ({ value }, { data }) =>
    createRender(CellActions, { ...value, data: toWritable(data) }),
    plugins: { sort: noSort, filter: noFilter }
});

You can get data from second param of cell method, but you get a ReadOrWritable store. So I did two method to convert it to Writable store

// store.svelte.ts
import { get, writable, type Readable, type Writable } from 'svelte/store';

export function isWritable<T>(
  store: Writable<T> | Readable<T>
): store is Writable<T> {
    // @ts-expect-error Test if store is writable
    return store?.update instanceof Function && store.set instanceof Function;
}
export function toWritable<T>(value: Writable<T> | Readable<T>): Writable<T> {
   if (isWritable(value)) return value;

    return writable(get(value));
}

Finally, inside my use:enhance of my form, i set my data :

data.update((rows) => {
    return rows.map((row) => {
        if (row.id === id) {
            return {
        ...row,
        registered: !registered
        };
    }
    return row;
    });
});

i hope it could help.