Changeset with radio buttons

I have a LiveView that creates a changeset on mount and validate.

defp build_changeset(data) do
    types = %{email: :string, distance_id: :integer}
    changeset = {data, types} |> Ecto.Changeset.cast(%{}, Map.keys(types)) |> Ecto.Changeset.validate_required([:email, :distance_id])
    changeset
end

And a simple form. It presents multiple options to the user, so I’m relying on a wrapping a radio

<.form as={:form} for={@changeset} :let={f} phx-change="validate" phx-submit="save">
    <.input field={f[:email]} type="email" />
    <%= for vd <- @distances do %>
      <label
        for={"form_distance_id_" <> to_string(vd.id)}>
        <input type="radio" id={"form_distance_id_" <> to_string(vd.id)} name="form[distance_id]" value={vd.id} class="sr-only" />
        <!-- various aesthetic elements -->
      </label>
    <% end %>
...

When I first click one of these labels, my validate event fires and I see params for my changeset:

Parameters: %{"_target" => ["form", "email"], "form" => %{"distance_id" => "23", "email" => "test@test.com"}}

However, if I start editing the email field, the distance_id is wiped away.

Parameters: %{"_target" => ["form", "email"], "form" => %{"email" => "test@test.com"}}

Without complete form values, I can only rebuild a partial changeset, thus wiping out prior user selections. Anything stand out?

Hey @boiserunner you need to set a checked attribute on the input that has the value you’ve set. Something like:

<input type="radio" ... checked={get_field(@changeset, :distance_id) == vd.id) />
2 Likes

Confirmed, this works.

Not a complete face-palm moment, but maybe like… 65%? 70%?

Thank you!

1 Like