LiveView tracking checkbox state

In liveView here, I am using checkbox. But this checkbox doesn’t track the state of the checkbox. So I would like an option where I can track the state of the checkbox, i.e…

  • if the checkbox id is already present inside the module attribute @changes, it removes the id from @changes (clicking twice is basically reverting back to original state so it doesn’t need to be saved)

  • if it is not already present in @changes, then add it along with state whether “true” or “false”.

  • I would like to handle it through a handle event function and store inside the module attribute @changes and use it else where in my code for further implementation.

I came across something called phx-click but I am not sure how to use it in my case here or how to handle it through handle_event to store inside @changes. Any thoughts??

<div class="sm:flex sm:items-start justify-center	w-80 min-w-full">
  <div class="w-80">
    <h2 class="modal-title"><%= @title %></h2>

    <%= f = form_for :cred_flags, "#",
      id: "cred_flags-form",
      phx_target: @myself,
      phx_submit: "save",
      class: "mt-4" %>
      <%= if @cred_flags == [] do %>
        <p class="mb-4">No Cred Flags have been created yet</p>
      <% else %>
        <table class="table-auto">
          <thead>
            <tr>
              <th class="px-2"></th>
              <th class="px-2 text-left">Flag Name</th>
            </tr>
          </thead>
          <tbody>
        <%= for f <- @flags do %>
            <tr>
              <td class="px-2"><%= checkbox(f, String.to_atom(f.id), value: Enum.member?(Enum.map(@cred_flags, & &1.flag_id), f.id), checked_value: true, unchecked_value: false, class: "mr-2") %>
              <td class="px-2"><%= f.flag_name %></span>
            </tr>
          <% end%>
          </tbody>
        </table>
      <div class="mt-5 mt-4 relative">
        <%= submit "Save", phx_disable_with: "Saving...", class: "btn-success" %>
      </div>
       <% end %>
    </form>
  </div>
</div>

There is also phx-change event, that will be sent to server when something in a form changes. You can also use this event instead of manually adding a click event to your checkbox.

See here for a sample

phx-change seems to do the work. I added phx-change like this in form_component.html.leex

<td class="px-2"><%= checkbox(f, String.to_atom(f.id), phx_change: "toggle", value: Enum.member?(Enum.map(@cred_flags, & &1.flag_id), f.id), checked_value: true, unchecked_value: false, class: "mr-2") %>

But how to get the ids and checkbox values?

def handle_event("save", %{"cred_flags" => crede_flags}, socket) do
    save_cred_flag(socket, socket.assigns.action, cred_flags)
  end

Here in cred_flags I get map of %{flag.id => boolean, flag.id => boolean}. But this returns the entire form and not just the changes.

defp save_cred_flag(socket, :edit_flags, cred_flags)do
    CredFlags.update_cred_flag(
           cred_flags
         )

          {:noreply,
          socket
          |> put_flash(:info, "Cred Flag updated successfully")
          |> push_redirect(to: socket.assigns.return_to)}
    end

Maybe try explaining what you want to do in a bigger picture. Are you trying to have some list of checkboxes?

phx-change is to be added on form, not individual inputs.

<%= f = form_for :cred_flags, "#",
      id: "cred_flags-form",
      phx_target: @myself,
      phx_submit: "save",
      phx_change: "change",
      class: "mt-4" %>

and a handler

def handle_event("change", %{"cred_flags" => crede_flags}, socket) do

where you will get the whole form as crede_flags when somethings in form changes. You can pattern match on individual form inputs if you want

def handle_event("change", %{"cred_flags" => %{"some-input-id" => input_value}}, socket) do

Also, module attributes (like @changes) are compile time values. You can’t “change” them in runtime. You can think of them like constants in other languages.