I want to render an array of objects, using an each block. I need to be able to remove elements from the array using callbacks from inside the each block. Also, for more complex UI-interactions, I need the reference to each component of the each-block to be available in the main app.
Here is my approach:
<script>
let items = [{text: "one"}, {text: "two"}];
function deleteItem(i) {
items.splice(i, 1);
items = items;
}
</script>
{#each items as item, i}
<button bind:this={items[i].ref} on:click={() => deleteItem(i)} >
{item.text}
</button>
<p />
{/each}
Understandibly, this leads to errors such as item[i] is undefined, because when the splicing of items is processed, the bind:this cannot properly be cleaned up anymore.
I tried to solve this by moving the component-references to a separate array. But no matter what I try, I cannot get the reference-array and the object-array to sync: Whenever deleteItem() is processed, I end up with null-values inside the refs-array. Here is one of my approaches (the each-section that prints the refs-array should help to show the null-values):
<script>
import {tick } from "svelte";
let items = [{text: "one", id: 1}, {text: "two", id:2}];
let refs = [];
async function deleteItem(i) {
items.splice(i, 1);
await tick();
refs.splice(i, 1);
items = items;
console.log(refs);
}
</script>
{#each items as item, i (item.id)}
<button on:click={async () => deleteItem(i)} bind:this={refs[i]}>
{item.text}
</button>
<p />
{/each}
{#each refs as ref}
{ref}
<p />
{/each}
I tried with and without tick(), tried inserting the tick() in different places, with and without async and with and without using (item.id) in the each block. How can I keep the references and the data in sync?