Ejemplo de eventos (y segunda parte)

En la segunda parte del ejemplo vamos a crear los componentes que quedan, que requieren un poco más de caso, antes de considerar este ejemplo como completado. Veremos cómo crear eventos propios y cómo propagar hacia arriba mediante binds.

Este curso ha sido marcado como anticuado y no está siendo revisado de forma activa. Es posible que la información pueda estar desactualizada o que los enlaces se hayan roto.

En este recorrido por la creación de formularios interactivos con Svelte, nos hemos centrado en cómo manejar eventos y binding para lograr una experiencia de usuario clara y funcional. Empezamos implementando un campo desplegable para seleccionar el sector laboral, usando un select con binding en su valor para que el estado se sincronice automáticamente con la opción elegida.

Para ello, definimos una lista de sectores como backend, frontend, devops y QA, y configuramos el valor inicial en frontend, aunque no fuera la primera opción en la lista. Esto nos permitió comprobar que el binding funciona correctamente, ya que el valor inicial se refleja en el desplegable sin importar su posición en las opciones.

Luego, creamos un componente personalizado llamado DropDown.svelte que recibe varias propiedades: un identificador para la etiqueta, un label para mostrar el texto descriptivo, una lista de opciones (choices) y un valor (value) que se bindea con el select. En el componente, usamos un label asociado al select y generamos las opciones dinámicamente a partir de la lista recibida, asignando el mismo string como valor y texto visible. El binding con bind:value asegura que cualquier cambio en el select actualice la variable del estado padre y viceversa.

<script>
  export let identifier;
  export let label;
  export let choices = [];
  export let value;
</script>

<p>
  <label for={identifier}>{label}</label>
  <select id={identifier} bind:value={value}>
    {#each choices as choice}
      <option value={choice}>{choice}</option>
    {/each}
  </select>
</p>

Al importar y usar este componente, pudimos verificar que el valor inicial se mostraba correctamente y que al cambiar la selección, el estado se actualizaba y se reflejaba en el formulario.

El siguiente paso fue crear un componente más complejo para manejar rangos salariales, llamado Rangos.svelte. Aquí nos alejamos del binding directo y optamos por usar eventos personalizados para manejar la interacción, lo que es útil cuando un componente tiene múltiples valores relacionados que queremos enviar como un solo objeto.

En Rangos.svelte, definimos propiedades para el identificador, la etiqueta, el valor mínimo y máximo permitidos, y usamos la función createEventDispatcher de Svelte para emitir eventos propios. El componente muestra dos controles deslizantes (input tipo range), uno para el valor mínimo y otro para el máximo, cada uno con su propia etiqueta que combina el identificador con un sufijo _min o _max para mantener la accesibilidad y claridad.

<script>
  import { createEventDispatcher } from 'svelte';

  export let identifier;
  export let label;
  export let minValue;
  export let maxValue;

  const dispatch = createEventDispatcher();

  let currentMin = minValue;
  let currentMax = maxValue;

  function cambiarMinimo(e) {
    const nuevoMin = parseInt(e.target.value);
    currentMin = nuevoMin;
    dispatch('update', { min: currentMin, max: currentMax });
  }

  function cambiarMaximo(e) {
    const nuevoMax = parseInt(e.target.value);
    currentMax = nuevoMax;
    dispatch('update', { min: currentMin, max: currentMax });
  }
</script>

<p>
  <label for="{identifier}_min">{label} mínimo</label>
  <input
    id="{identifier}_min"
    type="range"
    min="0"
    max="50000"
    value={currentMin}
    on:change={cambiarMinimo}
  />
</p>

<p>
  <label for="{identifier}_max">{label} máximo</label>
  <input
    id="{identifier}_max"
    type="range"
    min="0"
    max="50000"
    value={currentMax}
    on:change={cambiarMaximo}
  />
</p>

Al usar este componente en el formulario principal, escuchamos el evento update para actualizar el estado con los nuevos valores de mínimo y máximo. Esto mantiene sincronizados los valores y permite que el formulario refleje los cambios en tiempo real.

Además, implementamos una validación sencilla para evitar que el valor mínimo sea mayor que el máximo. Para ello, añadimos una propiedad error que, si no es nula, desactiva los inputs y muestra un mensaje de error. Esto evita que el usuario pueda enviar un formulario con datos incoherentes.

{#if error}
  <p>{error}</p>
{/if}

<input
  type="range"
  min="0"
  max="50000"
  value={currentMin}
  on:change={cambiarMinimo}
  disabled={error !== null}
/>

<input
  type="range"
  min="0"
  max="50000"
  value={currentMax}
  on:change={cambiarMaximo}
  disabled={error !== null}
/>

En el componente padre, comprobamos la coherencia de los valores y actualizamos el estado de error en consecuencia, lo que a su vez controla la habilitación o deshabilitación de los controles.

Finalmente, al enviar el formulario, podemos ver reflejados todos los valores introducidos, incluyendo el nombre, el sector seleccionado y el rango salarial, gracias a la correcta gestión de binding y eventos personalizados.

Con este enfoque, hemos aprendido a combinar binding directo en campos select con la creación de componentes personalizados que emiten eventos propios para manejar datos más complejos, como rangos numéricos con validación. Esto nos permite construir formularios semánticos, claros y funcionales en Svelte, facilitando la interacción y el mantenimiento del estado de manera organizada.

Lista de reproducción
  1. 1
    ¿Qué es Svelte?
    9 minutos
  2. 2
    ¿Cómo crear un proyecto de Svelte?
    7 minutos
  3. 3
    Creando nuestro primer componente
    7 minutos
  4. 4
    Datos dinámicos y props
    7 minutos
  5. 5
    Anidando componentes
    7 minutos
  6. 6
    Capturando eventos
    7 minutos
  7. 7
    Eventos y reactividad
    8 minutos
  8. 8
    Atributos condicionales e IF
    9 minutos
  9. 9
    Bucles
    11 minutos
  10. 10
    Bloques await
    7 minutos
  11. 11
    Bind
    8 minutos
  12. 12
    bind:this
    6 minutos
  13. 13
    ¿Para qué nos sirve un evento personalizado?
    6 minutos
  14. 14
    createEventDispatcher
    6 minutos
  15. 15
    Eventos con detalles
    7 minutos
  16. 16
    Reenviando eventos
    6 minutos
  17. 17
    Ejemplo de eventos (primera parte)
    12 minutos
  18. 18
    Ejemplo de eventos (y segunda parte)
    16 minutos
  19. 19
    Modificadores de eventos
    6 minutos
  20. 20
    Fundamentos del CSS con Svelte
    9 minutos
  21. 21
    Clases condicionales
    7 minutos
  22. 22
    Estilos en línea y variables CSS
    8 minutos
  23. 23
    Estilos globales
    6 minutos
  24. 24
    Importar hojas de estilo externas
    5 minutos
  25. 25
    Reactividad experta con el operador $
    8 minutos
  26. 26
    Slots (parte 1 de 2)
    5 minutos
  27. 27
    Slots (parte 2 de 2)
    7 minutos
  28. 28
    Directivas svelte:window, svelte:head, svelte:body
    4 minutos
  29. 29
    Actualizar de Rollbar a Vite 3
    11 minutos
  30. 30
    Exportar a Web Components
    10 minutos
  31. 31
    Integrar TypeScript, SCSS, PostCSS...
    8 minutos
  32. 32
    Hasta aquí (por ahora)
    3 minutos
  33. 33
    Lo que se viene con Svelte 5
    13 minutos