Ok, I think I got it to work:
I added a default to the client_type:
field :client_type, Ecto.Enum, values: [:legal_entity, :individual], default: :legal_entity
Then the new puts the correct embedded struct, depending on the `client_type`:
defp apply_action(socket, :new, _params) do
client = %Client{user_id: socket.assigns.current_scope.user.id}
client =
case client.client_type do
:legal_entity ->
%Client{client | client_name: %LegalEntityName{}}
:individual ->
%Client{client | client_name: %IndividualName{}}
end
socket
|> assign(:page_title, gettext("New client"))
|> assign(:client, client)
|> assign(:form, to_form(Clients.change_client(socket.assigns.current_scope, client)))
end
And when validating, if the `client_type` changed, I change the polymorphic_embed struct too:
@impl true
def handle_event("validate", %{"client" => client_params}, socket) do
changeset =
Clients.change_client(socket.assigns.current_scope, socket.assigns.client, client_params)
changeset =
case Ecto.Changeset.get_change(changeset, :client_type) do
nil -> changeset
:legal_entity -> Ecto.Changeset.put_change(changeset, :client_name, %LegalEntityName{})
:individual -> Ecto.Changeset.put_change(changeset, :client_name, %IndividualName{})
end
{:noreply, assign(socket, form: to_form(changeset, action: :validate))}
end
The problem with replacing the client_name on the changeset when `client_type` changes is that the previous values are lost, but is something I can live with.
Thanks!