Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<Table> Component Not Reactive in Flowbite-Svelte #1493

Open
izulwahidin opened this issue Nov 26, 2024 · 4 comments
Open

<Table> Component Not Reactive in Flowbite-Svelte #1493

izulwahidin opened this issue Nov 26, 2024 · 4 comments

Comments

@izulwahidin
Copy link

izulwahidin commented Nov 26, 2024

Bug Report: <Table> Component Not Reactive in Flowbite-Svelte

Description

The <Table> component in Flowbite-Svelte does not update reactively when its items prop (bound to a Svelte writable store) changes. Even though the data in the store updates correctly (as confirmed by logging), the table's UI does not reflect these changes.

Expected Behavior

The <Table> component should re-render automatically when the items array (bound to a Svelte writable store) is updated, such as when an item is deleted from the array.

Current Behavior

  • Data in the store updates correctly (confirmed via console.log).
  • The <Table> UI does not reflect the updated data unless additional workarounds are used (svelte each block).

Steps to Reproduce

  1. Create a writable store in Svelte to manage the table data:
    import { writable } from 'svelte/store';
    
    let tableData = writable([
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' },
    ]);
  2. Bind the store to the <Table> component:
    <Table items={$tableData} />
  3. Update the store by filtering out an item:
    tableData.update(data => data.filter(item => item.id !== 1));
  4. Observe that the data in tableData has changed, but the <Table> UI remains unchanged.

Additional Notes

This issue may be related to how the <Table> component processes changes to its items prop. It might not be tracking changes reactively or could require a specific update mechanism. Ensuring compatibility with Svelte's reactive stores would improve the developer experience significantly.

Reproduction

<script>
	import { writable } from 'svelte/store';
  	import { Table, TableBody, TableBodyCell, TableBodyRow, TableHead, TableHeadCell } from 'flowbite-svelte';
	import { Button } from 'flowbite-svelte';
	const tableData = writable([]);

	tableData.subscribe(data => console.log("data changed. currentData length is", data.length))

	tableData.set([
		{ id: 1, maker: 'Toyota', type: 'ABC', make: 2017 },
		{ id: 2, maker: 'Ford', type: 'CDE', make: 2018 },
		{ id: 3, maker: 'Volvo', type: 'FGH', make: 2019 },
		{ id: 4, maker: 'Saab', type: 'IJK', make: 2020 }
	])


	const handleDelete = async (removeId) => {
		tableData.update(currentData => currentData.filter(item => item.id !== removeId));
		alert(`deleted: ${removeId}`);
    };
</script>

<span>
currentData length: {$tableData.length}
</span>
<Table hoverable={true} items={$tableData}>
  <TableHead>
    <TableHeadCell sort={(a, b) => a.id - b.id}>ID</TableHeadCell>
    <TableHeadCell sort={(a, b) => a.maker.localeCompare(b.maker)} defaultSort>Maker</TableHeadCell>
    <TableHeadCell sort={(a, b) => a.type.localeCompare(b.type)}>Type</TableHeadCell>
    <TableHeadCell sort={(a, b) => a.make - b.make} defaultDirection="desc">Make</TableHeadCell>
    <TableHeadCell>
      <span class="sr-only">Buy</span>
    </TableHeadCell>
  </TableHead>
  <TableBody tableBodyClass="divide-y">
    <TableBodyRow slot="row" let:item>
      <TableBodyCell>{item.id}</TableBodyCell>
      <TableBodyCell>{item.maker}</TableBodyCell>
      <TableBodyCell>{item.type}</TableBodyCell>
      <TableBodyCell>{item.make}</TableBodyCell>
      <TableBodyCell>
		<Button on:click={()=>handleDelete(item.id)} color="red">Delete</Button>
      </TableBodyCell>
    </TableBodyRow>
  </TableBody>
</Table>

Flowbite version and System Info

System:
    OS: Windows 11 10.0.22631
    CPU: (8) x64 AMD Ryzen 3 7320U with Radeon Graphics
    Memory: 910.50 MB / 5.74 GB
  Binaries:
    Node: 20.12.2 - C:\Program Files\nodejs\node.EXE
    npm: 10.8.1 - C:\Program Files\nodejs\npm.CMD
    pnpm: 9.8.0 - ~\AppData\Local\pnpm\pnpm.EXE
    bun: 1.1.10 - ~\AppData\Roaming\npm\bun.CMD
  Browsers:
    Edge: Chromium (127.0.2651.86)
    Internet Explorer: 11.0.22621.3527
@thiagomagro
Copy link

Im having the same issue, changes on items are not triggering a rerender.

@izulwahidin
Copy link
Author

my current workaround of this problem is by using svelte each block instead of items arrays
{#each} {/each}

@thiagomagro
Copy link

The problem is you loose the Sorting functionality by using each blocks.

@izulwahidin
Copy link
Author

izulwahidin commented Dec 18, 2024

i mean you can create costum sorting

<script>
  import { Table, TableBody, TableBodyCell, TableBodyRow, TableHead, TableHeadCell } from 'flowbite-svelte';
  
  // Sample data array of objects
  let datas = [
    { name: 'Apple Watch 5', color: 'Red', category: 'Wearables', price: 999 },
    { name: 'Samsung Galaxy', color: 'Blue', category: 'Electronics', price: 799 },
    { name: 'Google Pixel', color: 'Black', category: 'Smartphones', price: 699 }
  ];

  // Sorting state
  let sortColumn = '';
  let sortDirection = 'asc';

  // Sorting function
  function sortTable(column) {
    // If clicking the same column, toggle direction
    if (sortColumn === column) {
      sortDirection = sortDirection === 'asc' ? 'desc' : 'asc';
    } else {
      // New column, default to ascending
      sortColumn = column;
      sortDirection = 'asc';
    }

    // Sort the data
    datas = datas.sort((a, b) => {
      // Handle different data types
      let valueA = a[column];
      let valueB = b[column];

      // Convert to number for price column
      if (column === 'price') {
        valueA = Number(valueA);
        valueB = Number(valueB);
      }

      // Comparison logic
      if (valueA < valueB) return sortDirection === 'asc' ? -1 : 1;
      if (valueA > valueB) return sortDirection === 'asc' ? 1 : -1;
      return 0;
    });
  }

  // Function to display sort indicator
  function getSortIndicator(column) {
    return sortColumn === column 
      ? (sortDirection === 'asc' ? '▲' : '▼') 
      : '';
  }
</script>

<Table striped={true}>
  <TableHead>
    <TableHeadCell on:click={() => sortTable('name')}>
      Product name {getSortIndicator('name')}
    </TableHeadCell>
    <TableHeadCell on:click={() => sortTable('color')}>
      Color {getSortIndicator('color')}
    </TableHeadCell>
    <TableHeadCell on:click={() => sortTable('category')}>
      Category {getSortIndicator('category')}
    </TableHeadCell>
    <TableHeadCell on:click={() => sortTable('price')}>
      Price {getSortIndicator('price')}
    </TableHeadCell>
    <TableHeadCell>
      <span class="sr-only">Edit</span>
    </TableHeadCell>
  </TableHead>
  <TableBody tableBodyClass="divide-y">
    {#each datas as data}
      <TableBodyRow>
        <TableBodyCell>{data.name}</TableBodyCell>
        <TableBodyCell>{data.color}</TableBodyCell>
        <TableBodyCell>{data.category}</TableBodyCell>
        <TableBodyCell>${data.price}</TableBodyCell>
        <TableBodyCell>
          <a href="/tables" class="font-medium text-primary-600 hover:underline dark:text-primary-500">Edit</a>
        </TableBodyCell>
      </TableBodyRow>
    {/each}
  </TableBody>
</Table>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants