Help with Ecto drop_param not working for 1 to 0 elements

I implemented a form with a one-to-many relationship using the checkbox trick.

Here is the relevant parts of my form

<.form for={@form} phx-target={@myself} phx-change="validate" phx-submit="save">

  ....
  
  <.inputs_for :let={compensation} field={@form[:compensation]}>
    <input type="hidden" name="member[compensation_order][]" value={compensation.index} />
    ....
    
    <label>
      <input
        type="checkbox"
        name="member[compensation_delete][]"
        class="hidden"
        value={compensation.index}
      />
      <span class="material-symbols-outlined">close</span>
    </label>
  </.inputs_for>
  
  <label>
    <input type="checkbox" name="member[compensation_order][]" class="hidden" />
    <span class="material-symbols-outlined">add</span>
    <span>Add compensation</span>
  </label>

</.form>

It is working fine for adding and removing child records, as long as there is at least one child left.

When I try to remove the last child, it does remove from the page, but when I click save, Ecto does not remove the record from the DB.

This is the params sent by the form during the validate event

%{
  "compensation" => %{
    "0" => %{
      "_persistent_id" => "0",
      "id" => "4",
      "member_id" => "14"
    },
    "1" => %{
      "_persistent_id" => "1",
      "id" => "7",
      "member_id" => "14"
    }
  },
  "compensation_delete" => ["1"],
  "compensation_order" => ["0", "1"],
}

This is the params sent by the form during the save event

%{
  "compensation" => %{
    "0" => %{
      "_persistent_id" => "0",
      "id" => "4",
      "member_id" => "14"
    }
  },
  "compensation_order" => ["0"],
}

This is the params sent by the form during the validate event when I try to remove the second and final child record

%{
  "compensation" => %{
    "0" => %{
      "_persistent_id" => "0",
      "id" => "4",
      "member_id" => "14"
    }
  },
  "compensation_delete" => ["0"],
  "compensation_order" => ["0"],
}

This is the params sent by the form during the save event after I removed the second and final child record

%{
// removed sent parent fields
}

As you can see, when I try to save the removal of the last child, the save event receives a map with no mention to the compensation delete or to the compensation record.

This causes ecto to think there is no change to the compensation.

So, I’m not sure if I’m doing something wrong during the validation process or during the form set up.

This is my validate event handler


@impl true
  def handle_event("validate", %{"member" => params}, socket) do
    form =
      socket.assigns.member
      |> Member.changeset(params)
      |> Map.put(:action, :validate)
      |> to_form()

    {:noreply,
     socket
     |> assign(:form, form)}
  end

Follow the docs in Phoenix.Component — Phoenix LiveView v0.20.7

You’re missing the hidden input for drop_param outside the inputs_for.

@LostKobrakai thank you. it worked