I’m having an issue setting up a live view, not sure what the correct way to accomplish this is.
I have a schema (Template) that has an embeds_many. I’d like to be able to use nested live components to add/update the nested Operations.
Schema:
schema "templates" do
field :name, :string
field :notes, :string
embeds_many :operations, Operation, on_replace: :delete
end
Currently, this lives in a live FormComponent that is a customized version of the FormComponent that mix phx.gen.live will add.
To add or update an Operation, it has its own UI, which is currently in its own live component, and it pops up in a modal. The user follows some steps here to prepare their Operation, which then has a “complete” button, which sends the event to the FormComponent. This is "add_operation".
The problems I’ve had is that when adding an Operation, the other changes to the form get lost because we create a new changeset, applying the params from the "add_operation" event to the existing Template in socket.assigns. When updating the regular text inputs, I can lose the added Operations for the same reason. And for saving the Template, I don’t know how to save the nested Operations without storing them in socket.assigns and then manually adding them to the form params on the "save" event.
This doesn’t seem to be quite the “nested forms” example, since the form for each nested Operation is ephemeral.
I’ve also tried the “checkboxes” approach from Chris McCord’s recent keynote ( https://youtu.be/FADQAnq0RpA?t=3160), giving each of my fields a hidden input and then using the normal markup to display each Operation, but I must be missing something because this doesn’t seem to actually add any items. If there are already Operations, the save event does seem to work as expected.
Changeset:
def changeset(template, attrs) do
template
|> cast(attrs, [:name, :notes])
|> cast_embed(:operations,
with: &Operation.changeset/2,
sort_param: :operations_order,
drop_param: :operations_delete
)
|> validate_required([:name])
end
and FormComponent
<.simple_form
for={@form}
id="template-form"
phx-target={@myself}
phx-change="validate"
phx-submit="save"
>
<.input field={@form[:name]} type="text" label="Name" />
<.input field={@form[:notes]} type="textarea" label="Notes" />
<.inputs_for :let={op_form} field={@form[:operations]}>
<input type="hidden" name="list[operations_order][]" value={op_form.index} />
<!--hidden inputs for Operation's fields-->
</.inputs_for>
<label class="...">
<input type="checkbox" phx-click="open_modal" name="list[operations_order][]" class="hidden" /> Add Operation
</label>
Has anyone here run into this kind of problem? I feel like there has got to be a sane way to use another live component to manage creation/editing of the items that are being embedded.






















