Búsqueda de sitios web

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.