One modal to edit embeds_many in a live_view form

Hello everyone!,

I’m dealing with a LiveView from that includes a dynamic list using an embeds_many where each item can be edited through a modal. The modal itself is a LiveComponent with it’s own form. When pressing the “save” of the modal it sends the data back for that item using send/2

Under normal circumstances I run the following code

def handle_event("validate", params, socket) do
    changeset = FormState.changeset(socket.assigns.struct, params["form_state"])
    {:noreply, assign(socket, changeset: changeset)}
end

But because this modal is not inside the form I need to “patch” the incoming data in to the changeset manually.

# in case of a single item
params = %{
  "list_of_things" => %{
    form_index => %{"id" => id, "something" => something}
  }
}

FormState.change_list_of_things(socket.assigns.struct, params)

This becomes harder when the list contains more than one item, because I actually have to built the whole list of params so the cast_assoc can track properly the changes ad

The problem here is that I feel that having to build params manually with the indexes feels a bit odd, and makes me have several questions but I don’t actually know how to handle this situation.

  • Should I have a modal per item in the has_many?
  • Does the modal should somehow update the form_field and trigger the phx-change event?
  • Is there any more proper solution to this problem?

For me the solution is to go with the phoenix way by triggering params by phx-change event, but I don’t fully see a proper solution for this problem

Thanks for the help!

Edit: typo

The modal itself is a LiveComponent with it’s own form

When you say it has its own form, do you mean form inputs that are part of a larger form, or each has its own <form>?

It would help too if you could share some heex code as I’m finding it a bit hard to picture exactly what you’re describing.

Hey, well I have something similar to the following

<.form for={@changeset} :let={form} phx-change="validate" phx-submit="save">
  <.inputs_for :let={child_form} field={@form[:list_of_things]}>
    <input class="hidden" value="encoded_value"/>
  </.inputs_for>
</.form>
<.live_component
  module={ModalComponent}
  selected_searchengine={@selected_item}
/>

(I’ve reduced it to the minimum)

But basically is modal that edits an item selected in a list. The result of this modal is a map, that get’s mapped to any number of <input class="hidden" value="value"/> inside the inputs_for.