javascript - Error en la aplicación Svelte: falló la conversión de cadena a booleano en la vista
En una aplicación Svelte, tengo este arreglo de países:
let countries = [
{
name:"Alegeria",
status: "1"
},
{
name:"Bulgaria",
status :"0"
}
]
Observa que la propiedad status es una cadena. Yo recorro el arreglo de esta manera:
{#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}
Como puedes ver, intento convertir el valor de la propiedad status a un booleano usando Boolean(Number(c.status)).
En lugar de la conversión deseada, obtengo el error: Solo se puede enlazar a un identificador (por ejemplo, foo) o a una expresión de miembro como muestra el REPL.
¿Qué estoy haciendo mal?
Respuesta #1
Como dice el error, solo puedes bind a un identificador o expresión de miembro, es decir, a una variable.
Esto se debe a que un bind es algo bidireccional, y si le has aplicado Boolean(Number(()), cuando alguien cambia esa entrada, Svelte no sabe cómo deshacer esas funciones para 'guardar' los datos de vuelta en la variable a la que está vinculado.
Si no puedes cambiar las variables de estado a booleanas (mejor solución, como sugieren otras respuestas), necesitas hacer manualmente esta actualización bidireccional. Elimina el bind, solo utiliza checked={Boolean(Number(c.status))}, y maneja el evento change del input para convertir de true/false de nuevo a "1" o "0", y guarda eso en el estado.
Usar :
function handleClick(country) {
countries.find(c => c.name == country.name).status = (country.status == "1") ? "0" :"1"
}
y
<Switch checked={Boolean(Number(c.status))} on:change={() => handleClick(c)}/>
Véalo funcionando en este repl
Respuesta #2
Creo que el problema es que la función Boolean() crea un nuevo objeto, al que no se puede enlazar, porque nunca se vuelve a referenciar. Puedes enlazarte directamente a tu arreglo de valores en countries, usando este código:
{#each countries as c, index}
<tr>
<td>{c.name}</td>
<td class="text-right"><Switch bind:checked={countries[index].status} /></td>
</tr>
{/each}
Lo que ha cambiado es que ahora usas el parámetro index del bucle #each para enlazar con la variable del arreglo de países. Ten en cuenta que, para que esto funcione correctamente, necesitas cambiar los valores de estado a true o false. De lo contrario, seguirá funcionando, pero el valor inicial siempre será true.
