Bear with me, Svelte newbie question coming.
I have a selection based Master/Detail view like the following simplified version:
<script>
let data = [{ x: 10},{ x: 20},{ x:30}]
let selected = data[1];
</script>
<table>
{#each data as row}
<tr>
<button class="{selected === row ? 'selected' : ''}"
on:click={() => selected = row}>Select</button>
<td><input type="number" bind:value={row.x}/></td>
</tr>
{/each}
</table>
<br/><br/>
Detail: <input type="number" bind:value={selected.x}/>
<style>
.selected { background-color: #ff3e00; color: white; }
</style>
This works correctly if you select different rows (the Detail updates with the selected row).
Unfortunately, however, the Detail does not update if the value of the selected item in the top list is changed. Also, the list item value does not update if the Detail is changed. A side note: If you change the list value, then select a different item and switch back, the Detail view does show the correct value.
To fix it, I switched to an index based selection:
<script>
let data = [{ x: 10},{ x: 20},{ x:30}]
let selectedIndex = 1;
$: selected = data[selectedIndex];
</script>
<table>
{#each data as row, i}
<tr>
<button class="{selectedIndex === i ? 'selected' : ''}"
on:click={() => selectedIndex = i}>Select</button>
<td><input type="number" bind:value={row.x}/></td>
</tr>
{/each}
</table>
<br/><br/>
Detail: <input type="number" bind:value={selected.x}/>
<style>
.selected { background-color: #ff3e00; color: white; }
</style>
What I can’t figure out is why the first version doesn’t work? What magic am I missing? Further, why did the second version fix it? Both, to me, seem like they should behave the same.
I really like Svelte, but before I can invest heavily I need to know it truly does handle all reactive updating correctly.
>Solution :
Svelte does not know that row.x and selected.x might be referring to the same thing, which is why the first version of the code does not work as expected.
The second version only works because of this reactive statement:
$: selected = data[selectedIndex];
Changes to row.x invalidate data and that causes the reactive statement to be reevaluated, thus updating selected.x. Changes to selected.x are propagated to row.x because data and selectedIndex are invalidated on change, since they are used in the reactive statement.
Essentially the reactive statement establishes the logical relationship between selected and data which would otherwise not be visible to the Svelte compiler.