Hi everyone,
I have this use case where I want to edit an association of an enitity (with a belongs_to
relationship) where user has the option to select the value for the associate field from a list or create a new one.
Here is an example of the schemas:
schema "employee" do
field :name, :string
belongs_to :employer, Employer, on_replace: :update
end
def changeset(employee, attrs) do
employee
|> cast(attrs, [ :name ])
|> cast_assoc(:employer)
and
schema "employer" do
field :name, :string
has_many :employees, Employee
end
def changeset(employer, attrs) do
employer
|> cast(attrs, [ :name ])
The user should be able to edit the employee and set it’s employer. The UI is supposed to look like this:
My question is basically what is the right way to do this? Since I’m new to the Elixir, I’m lacking the good practice for this case.
My approach so far:
- Preloading the Employer
- Adding some params for the radio button and the text input which are not in the schema
<.input type="radio" id="existing" field={@form[:existing_or_new]} value="existing" label={...} />
<.inputs_for :let={employer} field={@form[:employer]}>
<.input field={employer[:id]} type="select" options={@employer_options} />
</.inputs_for>
<.input type="radio" id="new" field={@form[:existing_or_new]} value="new" label={...} />
<.input type="text" field={@form[:new_employer_name]} />
- Setting some default values in form assignment function
def assign_form(socket, changeset) do
base_form = to_form(changeset)
new_params =
base_form.params
|> Map.put_new("existing_or_new", "existing")
|> Map.put_new("new_employer_name", "")
form = Map.put(base_form, :params, new_params)
assign(socket, form: form)
end
- And finally update the employee:
def update_employee(%Employee{} = employee, attrs) do
employee
|> Employee.changeset(attrs)
|> Ecto.Changeset.put_assoc(:employer, attrs["employer"])
|> Repo.update()
end
But the inputs_for
adds a _persistent_id
which causes the following error:
field names given to change/put_change must be atoms, got: `"_persistent_id"