DEV Community

Charles Loder
Charles Loder

Posted on

Svelte: set a default radio button with bind

I've just started using Svelte, and it's been really fun to work with!

Today, I did, however, run into a little quirk with radio buttons. If you use the bind directive, there is no way to have a radio button checked by default.

bind directive

In Svelte, you can use element directives, and particularly helpful for radio buttons is the bind directive.

Basically, you can group a number of radio inputs together. Here is the example from Svelte's docs:

<script>
  let tortilla = 'Plain';

  /** @type {Array<string>} */
  let fillings = [];
</script>

<!-- grouped radio inputs are mutually exclusive -->
<input type="radio" bind:group={tortilla} value="Plain" />
<input type="radio" bind:group={tortilla} value="Whole wheat" />
<input type="radio" bind:group={tortilla} value="Spinach" />
Enter fullscreen mode Exit fullscreen mode

It's pretty straightforward — all these inputs are bound together as part of the group "Plain".

Note: if the variable were named group instead of tortilla, you can just write bind:group, which is nice.

If you were to create a Svelte repl you would notice that when the code compiles, no radio buttons are checked.

That may be ok in some situations, but I wanted to ensure that at least one is checked.

The solution is a lifecycle hook.

onMount hook

Like most component libraries, Svelte allows you to hook into the components lifecycle.

For this issue, the onMount hook is needed.

Now, when the component is mounted, I can can check if there are any checked inputs. If not, then I check the first:

onMount(() => {
  const inputs = document.querySelectorAll("input");
  const hasChecked = Array.from(inputs).some((input) => input.checked);
  if (!hasChecked) {
    inputs[0].checked = true;
  }
});
Enter fullscreen mode Exit fullscreen mode

That's it!

Here is a full example and a link to a repl.

<script>
  import { onMount } from "svelte";
  let group = "philosophers"
  const options = ["Søren Kierkegaard", "Jean-Paul Satre", "Simone de Beauvoir", "Albert Camus"];

  onMount(() => {
    const inputs = document.querySelectorAll("input");
    const hasChecked = Array.from(inputs).some((input) => input.checked);
    if (!hasChecked) {
      inputs[0].checked = true;
    }
});

</script>

<div class="question">
  <legend>Who is your favorite existentialist philosopher?</legend>
  {#each options as option}
    <div class="option">
      <input type="radio" id={option} bind:group value={option}>
      <label for={option}>{option}</label>
    </div>
  {/each}
</div>

<style>
  div.question {
    display: flex;
    flex-direction: column;
  }
</style>
Enter fullscreen mode Exit fullscreen mode

Hopefully, this helps anyone else who encounters this issue.

Top comments (0)