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 atributonamede 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 utilizabind: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 convertirinput.valuemanualmente 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 ainput.checkedmediantebind: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:valuecon 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,
selectedseráundefined, por lo que no se puede acceder directamente a algo comoselected.idsin verificar antes