Saltar al contenido principal

Bindings

  • Por regla general, el flujo de datos en Svelte es de arriba hacia abajo: un componente padre puede establecer propiedades en un componente hijo, y un componente puede establecer atributos a un elemento, pero no al revés
  • Los bindings (bind:) rompen esa regla de forma explícita, y no aplican solo a inputs de texto: funcionan con <textarea>, <select>, checkboxes, radios, y en general con cualquier elemento/componente que exponga un valor vinculable
  • Describen un enlace bidireccional (two-way binding): el valor de la variable se refleja en el elemento, y los cambios en el elemento actualizan la variable automáticamente

Text inputs

App.svelte
<script>
let name = $state("world");
</script>

<input bind:value={name} />

<h1>Hello {name}</h1>

Esto significa que, así como los cambios en name actualizan el <input>, los cambios en el <input> también actualizarán name.

¿Cuándo es realmente útil?

  • En un <form> HTML tradicional no haría falta, porque el navegador toma los valores directamente del atributo name de cada input al enviar
  • En Svelte normalmente se intercepta el submit con JS, así que ahí sí importaría tener el valor sincronizado
  • Pero el caso de uso real va más allá del submit: bind: sirve cuando la UI necesita reaccionar al valor mientras el usuario escribe o interactúa, no solo al final
    • Validación en vivo (ej. "mínimo 3 caracteres")
    • Contador de caracteres
    • Vista previa en tiempo real (ej. editor Markdown)
    • Habilitar/deshabilitar un botón según si el input es válido
    • Filtrar una lista mientras se escribe en un buscador

Textarea inputs

  • El elemento <textarea> se comporta igual que un input de tipo string, se utiliza bind:value
  • Cuando el nombre de la variable coincide con el del atributo, se puede usar la forma abreviada bind:value (sin ={value}); esto aplica a todos los bindings, no solo a <textarea>
App.svelte
<script>
let value = $state("");
</script>

//<textarea bind:value={value}></textarea>
<textarea bind:value></textarea>

<p>{value}</p>

Numeric inputs

  • En el DOM, todo valor de un input es un string. Esto no es útil para entradas numéricas (type="number", type="range"), donde normalmente habría que convertir input.value manualmente antes de usarlo
  • Con bind:value, Svelte hace esa conversión automáticamente
App.svelte
<script>
let a = $state(1);
let b = $state(2);
</script>

<label>
<input type="number" bind:value={a} min="0" max="10" />
<input type="range" bind:value={a} min="0" max="10" />
</label>

<label>
<input type="number" bind:value={b} min="0" max="10" />
<input type="range" bind:value={b} min="0" max="10" />
</label>

<p>{a} + {b} = {a + b}</p>

Checkbox inputs

  • Los checkbox se utilizan para alternar entre estados
  • En lugar de vincularse a input.value, se vincula a input.checked mediante bind:checked
App.svelte
<script>
let yes = $state(false);
</script>

<label>
<input type="checkbox" bind:checked={yes} />
Yes! Send me regular email spam
</label>

{#if yes}
<p>Thank you. We will bombard your inbox and sell your personal details.</p>
{:else}
<p>You must opt in to continue.</p>
{/if}

<button disabled={!yes}>Subscribe</button>

Select bindings

  • También se puede usar bind:value con elementos <select>
  • El valor de cada <option> puede ser un objeto y no solo un string; Svelte lo maneja igual
App.svelte
<script>
let questions = [
{ id: 1, text: "Where did you go to school?" },
{ id: 2, text: "What is your mother's name?" }
];

// El estado se inicializa vacío
let selected = $state();
let answer = $state("");

function handleSubmit(e) {
e.preventDefault();
alert(`Answered question: ${selected.id} - ${selected.text}: ${answer}`);
}
</script>

<h2>Insecurity questions</h2>

<form onsubmit={handleSubmit}>
<select bind:value={selected} onchange={() => (answer = "")}>
{#each questions as question}
<option value={question}>{question.text}</option>
{/each}
</select>

<input bind:value={answer} />

<button disabled={!answer} type="submit">Submit</button>
</form>

<p>Selected question {selected ? selected.id : 'waiting...'}</p>
  • No se estableció un valor inicial para selected; el binding le asigna automáticamente el valor predeterminado (el primer <option> de la lista)
  • Pero hasta que el binding se inicialice, selected será undefined, por lo que no se puede acceder directamente a algo como selected.id sin verificar antes

Group inputs

Select multiple