Submitting an array of checkboxes

Hey folks,

Can’t for the life of me figure this out. I’m doing a CSV import screen. The user uploads a CSV of users to invite, I display their details on a table with checkboxes to select which to invite. The user checks the boxes, clicks Send, invitations go out. I store the array of CSV data in the session, so ultimately what I want is something like:

selected = [false, true, true] # All but first row selected

The closest I’ve come is:

<%= form_for @conn, Routes.admin_user_path(@conn, :send_bulk_invitation), [as: :bulk_invite], fn f -> %>
  <table>
    <thead>
      <th>Select</th>
      <%= for header <- @headers do %>
        <th><%= header %></th>
      <% end %>
    </thead>
    <tbody>
      <%= for {row, index} <- Enum.with_index(@data) do %>
        <tr>
          <td>
            <%= checkbox(f, "selected[#{index}]", value: true) %>

That gives me something like selected = %{"0" => "true", "1" => "true", "10" => ...}

I mean, I guess I can iterate through that, convert the strings to numbers, build up an array…but is there no way to flatten a field into an array of checked boxes? Other things I’ve tried:

<%= checkbox(f, "selected[]", value: true) %>
<%= checkbox(f, "selected", name: "selected[]", value: true) %>
# And probably a few others I've forgotten

Help very much appreciated. Thanks!

There is a way but it would involve JS. I’d say don’t do it and just make double sure you are generating a list of booleans in the right order on your server side:

    http_input = %{"0" => "true", "1" => "false", "2" => "true", "3" => "false"}
    http_input
    |> Enum.map(fn {key, val} ->
      {String.to_integer(key), if(val == "true", do: true, else: false)}
    end)
    |> Enum.sort_by(& elem(&1, 0))
    |> Enum.map(& elem(&1, 1))

Which returns [true, false, true, false] as it should.

(The conversion in the first Enum.map can be done better but I’ll leave that to you.)

1 Like