Context: I’m building an Echo schema that embeds_one
schema which itself contains an embeds_many
field. I need to allow users to add and remove from the embeds_many field. I followed the tutorial provided in the Phoenix.Component.inputs_for/1 documentation hoping to take advantage of Ecto.Changeset.cast_embed
’s :sort_param
/:drop_param
.
Problem: When embeds are cast, the drop param gets treated as a new embedded entity and gets passed to changeset for validation. Of course this crashes every time the form is modified as drop param is a list of indexes and not a map of user input data. The docs linked above state:
Outside the
inputs_for
, we render an emptymailing_list[emails_drop][]
input, to ensure that all children are deleted when saving a form where the user dropped all entries. This hidden input is required whenever dropping associations.
In my case since this is an embeds_many
inside of an embeds_one
, my empty input looks like this patron[menu_item][modifications][mods_drop][]
. When the empty form is validated the value [""]
gets passed to my changeset function. When delete is pressed on a populated form, the index gets passed to the changeset function like so ["1"]
(populated in mount, can’t edit form in UI as it crashes on every change).
The data passed to LiveView on change looks like so:
%{
"_persistent_id" => "0",
"item_name" => "",
"modifications" => %{
"0" => %{
"_persistent_id" => "0",
"comment" => ""
},
"mods_drop" => [""],
"mods_sort" => ["0"]
}
}
If mods_drop => ["3"]
then ["3"]
gets passed to the modifications changeset. If I comment out the hidden mods_drop
input, the same problem occurs, this time on the mods_sort
input. I feel I must be missing something crucial in the docs but I’m not sure what.