How to add data when dynamically adding inputs using inputs_for + sort_param/drop_param?

I know this post is pretty old nevertheless I wanted to share my approach for this.

I use sort_param to achieve adding an item of the same type with different configurations.

Here is what I do to achieve this:

~H"""
<.inputs_for :let={f} ...>
  <.button name="sort_param[]" value={JSON.encode!(%{attribute: "initial_attribute_value"})}>Add new entity</.button>
  <.input type="hidden" field={f[:_existing_relation]} />
</.inputs_for>
"""

Then I use a dedicated changeset function header to handle the add-case

def changeset(entity, %{"sort_param" => [initial_attrs]} = attrs) do
  initial_relation_attrs = JSON.decode!(initial_attrs)

  entity
  |> cast(attrs, [])
  |> cast_assoc(:relation, sort_param: :sort_param, with: &MyRelation.changeset(&1, &2, initial_relation_attrs)
end

def changeset(entity, attrs) do
  # handle other change
end

An last but not least I use a dedicated changeset function header to handle changing the relation:

def changeset(relation, %{"_existing_relation" => _} = attrs, _initial_attrs) do
  # we can ignore initial_attrs for this changeset since this is an existing relation

  ...
end

def changeset(relation, _attrs, initial_attrs) do
  # attrs is always empty when adding, use initial_attrs instead to build the changeset
  ...
end

Hope this helps anyone who might find this post later :slight_smile: