In a Svelte app, I have this array of countries:
let countries = [
{
name:"Alegeria",
status: "1"
},
{
name:"Bulgaria",
status :"0"
}
]
Note the status
property is a string. I iterate the array this way:
{#if countries.length > 0}
<table class="table">
<thead>
<tr>
<th>Country</th>
<th class="text-right">Status</th>
</tr>
</thead>
<tbody>
{#each countries as c}
<tr>
<td>{c.name}</td>
<td class="text-right"><Switch bind:checked={Boolean(Number(c.status))} /></td>
</tr>
{/each}
</tbody>
</table>
{:else}
<p class="alert alert-danger">No countries found</p>
{/if}
As you can see, I try to convert the value of the status
property to a boolean this by using Boolean(Number(c.status))
.
Instead of the desired conversion I get the error: Can only bind to an identifier (e.g.
foo) or a member expression
as the REPL shows.
What am I doing wrong?
As it says in the error, you can only bind
to an identifier or member expression - ie a variable.
This is because a bind
is a two-way thing, and if you have applied Boolean(Number(())
to it, when someone changes that input, then svelte doesn't know how to undo those functions to 'save' the data back into that variable it's bound to.
If you can't change the status variables to be boolean (better solution, as suggested by other answers), you need to manually do this two-way updating. Drop the bind
, just have checked={Boolean(Number(c.status))}
, and handle the input's change
event to convert from true/false back into "1" or "0", and save that to the status.
Use:
function handleClick(country) {
countries.find(c => c.name == country.name).status = (country.status == "1") ? "0" :"1"
}
and
<Switch checked={Boolean(Number(c.status))} on:change={() => handleClick(c)}/>
See it working in this repl