Handle_event/3 gets no params on unchecked box?

So, I want LiveView to keep track of a set of checkboxes and know which ones are checked and which are not. The purpose of this is to keep track of, and modify, a many_to_many association between billing_categories and credit_cards.

In my .html.heex I have:

    <div>
        <%= category %>:
        <input checked={category in @changeset.data.billing_categories} type="checkbox" phx-click="flip" value={category}>
        </div>
    <% end %>

And then in my live controller:

  def handle_event("flip", params, socket) do
    IO.inspect(params, label: "Well looky here!")
    {:noreply, socket}
  end

When I check the box with the name "1", I get this in the terminal from inspecting the params:

Well looky here!: %{"value" => "whoa!"}

But when I uncheck a box, I just get:

Well looky here!: %{}

If I could just get handle_event/3 to know which box has been unchecked, I could take care of the rest. Is there some simpler way to do this?

You can use a with the same name as the checkbox and set its value to whatever you want.

this is what it looks like in the core_components.ex from phoenix_live_view

  def input(%{type: "checkbox"} = assigns) do
    assigns = assign_new(assigns, :checked, fn -> input_equals?(assigns.value, "true") end)

    ~H"""
    <label phx-feedback-for={@name} class="flex items-center gap-4 text-sm leading-6 text-zinc-600">
      <input type="hidden" name={@name} value="false" />
      <input
        type="checkbox"
        id={@id || @name}
        name={@name}
        value="true"
        checked={@checked}
        class="rounded border-zinc-300 text-zinc-900 focus:ring-zinc-900"
        {@rest}
      />
      <%= @label %>
    </label>
    """
  end
1 Like

Pardon me, but can use a what? Your sentence appears to be missing a word there! :slight_smile:

The behaviour you see is how html is supposed to work. Unchecked checkboxes are ignored when gathering a forms data.

I‘d suggest using the form helpers of phoenix to build checkboxes. They automatically add an hidden input as well (before the checkbox), which uses the same name and has an „unchecked“ value. So when the checkbox is not checked you get the value of the hidden input – when the checkbox is checked you get the value of the checkbox, which overrides the hidden input value.

1 Like

My bad, to mark it as code,

there was a
<input type="hidden" name={@name} value="false" />

like in the example below

1 Like