问题
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?
回答1:
I think the problem is that the Boolean() function creates a new object, to which you can't bind, because it is never again referenced. You can bind directly to your array of values in countries
, using this code:
{#each countries as c, index}
<tr>
<td>{c.name}</td>
<td class="text-right"><Switch bind:checked={countries[index].status} /></td>
</tr>
{/each}
What has changed is that you use the index
parameter of the #each
loop now to bind to the variable of the countries array. Please be aware that in order for this to properly work, you need to change the status values to true
or false
. Otherwise it will still work, but the initial value will always be true
.
回答2:
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
来源:https://stackoverflow.com/questions/63014165/svelte-application-bug-converting-string-to-boolean-in-the-view-fails