How to make a form where you can select a belongs_to element from dropdown, then change assoc

I’d like to have a form where the user can select a belongs_to element, and update the fields on that element in the same transaction. I’m in LiveView. This is the form:

I want to change the Element, have Elixir look up the associated element, change the text fields to those of the chosen element, and allow the user to update them. When they hit save, I’d like to run the update routine that updates the db.

How do I/is it possible to change the x_id field, and the x field of a belongs_to relationship in the same change?
This form has been kicking my buttfor months. My main data type is structured like this:

defmodule UserDocs.Automation.Step do
  schema "steps" do
    ...
    belongs_to :element, Element, on_replace: :update
    ...
  end

Essentially what I want to do is, when the user picks a different Element, I want the nested form to update with the data from the selected element, and for the user to be able to immediately update the nested form. I’ve run into a gamut of problems.

My main problem is that when I try to change the x_id and the embed at the same time, I run into the on_replace errors, and I can’t figure out which one to use. I think I’m just approaching this wrong.
I changed this to update the FK’s and then reloading the data and putting it on the form. However, I use the changeset to decide which records to broadcast, so I need the whole changeset. Any ideas?

Here’s basically what I’m doing now (function names should describe pretty well

  def update_step_with_nested_data(%Step{} = step, attrs, state) do
    IO.inspect(Enum.count(state.assigns.data))
    with changeset <- Step.change_nested_foreign_keys(step, attrs), # get the changeset with updated foreign keys
      { :ok, step } <- Repo.update(changeset), # Apply to database and get new step
      step <- update_step_preloads(step, changeset.changes, state), # Preload data according to changes
      changeset <- Step.change_remaining(step, changeset.params), # Apply the changeset to the remaining fields
      { :ok, step } <- Repo.update(changeset) # Apply the changes to the database
    do
      { :ok, step }
    else
      err -> err
    end
  end
1 Like