Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind variable declared with Svelte let directive?

Tags:

svelte

I'm trying to workaround "Cannot bind to a variable declared with the let: directive" error.

// FancyList.svelte
<script>
    export let items = []   
</script>

<ul>
    {#each items as item, i}
        <li><slot item={item}></slot></li>
    {/each} 
</ul>

// App.svelte
<script>
    import FancyList from './FancyList.svelte'
    let items = [ {x: 'AX', y: 'AY'}, {x: 'BX', y: 'BY'}, {x: 'CX', y: 'CY'}]
</script>

<FancyList bind:items={items} let:item={item}>
    <input type=text bind:value={item.x}>
    <input type=text bind:value={item.y}>
</FancyList>

Available as Svelte REPL

Things I have tried so far

1) Making FancyList to pass item index instead of item itself and binding items[index] instead of item.

<FancyList items={items} let:index={index}>
    <input type=text bind:value={items[index].x}>
    <input type=text bind:value={items[index].y}>
</FancyList>

Available as Svelte REPL

This will initially render properly but will emit "ReferenceError: index is not defined" error upon input value change.

2) Making FancyList to pass onChange callback and not using bind.

<FancyList bind:items={items} let:item={item} let:onChange={onChange}>
    <input type=text value={item.x} on:input={e => onChange({...item, x: e.target.value})}>
    <input type=text value={item.y} on:input={e => onChange({...item, y: e.target.value})}>
</FancyList>

Available as Svelte REPL.

This works but is significantly more verbose.

like image 888
Jan Tvrdík Avatar asked Jun 29 '19 11:06

Jan Tvrdík


Video Answer


2 Answers

It's a bug that your first solution attempt didn't work — I've raised an issue. Another possible workaround is to put the update logic in the parent component, so that the child component doesn't need to have any special awareness of the parent's requirements: https://svelte.dev/repl/2d13c33c34f445d99618fbb1bc8bebb9?version=3.6.1. It's about the same as your second solution, verbosity-wise.

like image 115
Rich Harris Avatar answered Oct 16 '22 23:10

Rich Harris


You can use svelte:component to accomplish this. It basically will let you pass a component to your FancyList, making it a Higher Order Component of sorts.

Here's a REPL example that shows it working:

https://svelte.dev/repl/bc985c21735f4b2a9945f1ddc74988e6?version=3.6.1

like image 2
suddjian Avatar answered Oct 16 '22 23:10

suddjian