I cannot empty previous selection when changing options between related Shoelace Selects in Svelte. I tried to force Shoelace select value but it didn't work, maybe I shouldn't use two-way binding or there is another workaround when working with Shoelace and Svelte.
I have an array of trees, where trees have branches.
<script>
import { trees } from './data'
import Select from './Select.svelte'
let id_trees = '1'
let id_branches = '1'
$: branches = trees.find(tree => tree.id == id_trees).branches
</script>
<Select label="Trees" bind:value={id_trees}>
{#each trees as { id, name }}
<sl-option value={id}>{name}</sl-option>
{/each}
</Select>
<Select label="Branches" bind:value={id_branches}>
{#each branches as { id, name }}
<sl-option value={id}>{name}</sl-option>
{/each}
</Select>
If I change from tree A to B and C render works as expected:
but if I go back to tree A then branch C1 remains:
Here a minimal working example:
https://svelte.dev/repl/367d0371c1c34b09912f3a2a381c8234?version=4.2.10
Update: variable for the branch selection remains the same
key
and object identity solutions are wonderful but they only affects the render. I though using object identity would empty the real value but it doesn't. How can we empty the id_branches
selection?
Same working example where I chose different ids to show that changing trees doesn't empty/change id_branches:
https://svelte.dev/repl/94f43b27eb22435198643b2fe92206b5?version=4.2.10
Solution:
brunnerh answer and comments solved the issue!
The component does not appear to update based on the text content change of the option (the value
potentially remains the same).
In situations like this, a simple workaround is to recreate the affected part of the component via {#key}
. So in this case you could do this:
{#key branches}
<Select label="Branches" bind:value={id_branches}>
{#each branches as { id, name }}
<sl-option value={id}>{name}</sl-option>
{/each}
</Select>
{/key}
This way, the dependent select is fully updated if its options list changes.
You also can force the recreation of the options in the {#each}
by providing a key (see docs) that can distinguish between the branch items of the different trees, e.g. by using the object identity of the items:
<Select label="Branches" bind:value={id_branches}>
{#each branches as item (item)}
{@const { id, name } = item}
<sl-option value={id}>{name}</sl-option>
{/each}
</Select>
This however will cause the selection to be cleared on tree change, even if the option value
would exist.