vincjo / datatables

A toolkit for creating datatable components with Svelte
https://vincjo.fr/datatables
MIT License
363 stars 15 forks source link

Radio button group issue #62

Closed Josh-Nicholson closed 9 months ago

Josh-Nicholson commented 10 months ago

I'm currently experiencing a weird issue around filters and radio buttons.

In my table I have a column that is displaying a radio button group. Here is the code:

<table>
  <thead>
    <tr>
    <th class="sticky top-0 border-b border-black">User</th>
    <Th {handler} orderBy="firstName" class="sticky top-0 border-b border-black">First Name</Th>
    <Th {handler} orderBy="lastName" class="sticky top-0 border-b border-black">Last Name</Th>
    <th class="sticky top-0 border-b border-black"></th>
    </tr>
  </thead>
  <tbody>
    {#each $rows as row}
    <tr>
        <td>{row.firstName}</td>
        <td>{row.lastName}</td>
        <td>
              {#each [0, 1, 2] as permission}
            <label class="flex items-center space-x-2">
            <input
                class="radio"
                type="radio"
                bind:group={row.applicationPermission}
                name={`userpermissions-${row.id}`}
                on:change={() => updatePermissions(row.id, permission)}
                value={permission}
            />
            {#if permission == 0}
                <p>Not shared</p>
            {:else if permission == 1}
                <p>View</p>
            {:else}
                <p>View & Edit</p>
            {/if}
            </label>
              {/each}
    </td>
    </tr>
    {/each}
  </tbody>
</table>

On table load everything is fine. The radio button groups are checked correctly according to the value of row.applicationPermission However when applying a filter, some of the rows have their radio button group become unchecked.

I've placed logging statements everywhere and the values are correct so the radio should be checked accordingly but they aren't. The strange thing is that only a few lose being checked, most rows are fine. Its also not with one specific value, it can happen with different applicationPermission values.

Example images: No filter

image

Filter applied

image

The issue does however go away if you order one of the columns in the table. For example if you click the First Name column and reorder it, all the radio buttons get the correct checked value back.

vincjo commented 10 months ago

I've no idea why.

If you use checked={row.applicationPermission === permission} instead of bind:group ?

It's an alternative, since row.applicationPermission comes from a derived store, it should update dynamically without the bind directive.

This is a quick answer, it may require further investigation.

Josh-Nicholson commented 10 months ago

Just tried it with checked instead of bind:group

Unfortunately the same issue is happening. Even tried having checked call off to a function, but still doesn't work.

vincjo commented 10 months ago

Ok, i'm going to make a repro. I keep you in touch

Josh-Nicholson commented 10 months ago

Thank you

vincjo commented 10 months ago

I just thought about it, have you tried using keyed each block for radio buttons? image https://learn.svelte.dev/tutorial/keyed-each-blocks

Josh-Nicholson commented 10 months ago

Permission in this instance is just a number, either 0, 1 or 2. image

I have tried the following, but the issue still remains image

vincjo commented 9 months ago

It seems the problem comes from svelte rendering the DOM. Idk the reason why exactly.

Instead of an each block, dupplicating HTML works:

<td>
    <label class="flex items-center space-x-2">
        <input type="radio" checked={row.permission === 0} 
            on:change={() => console.log(`changed to ${0}`)}
        />
        <p>Not shared</p>
    </label>
    <label class="flex items-center space-x-2">
        <input type="radio" checked={row.permission === 1} 
            on:change={() => console.log(`changed to ${1}`)}
        />
        <p>View</p>
    </label>
    <label class="flex items-center space-x-2">
        <input type="radio" checked={row.permission === 2} 
            on:change={() => console.log(`changed to ${2}`)}
        />
        <p>View & Edit</p>
    </label>
</td>

https://vincjo.fr/datatables/test/radio-group