How is one supposed to display the polymorphic embed fields in a form if the schema is empty?
First of all, thanks a ton for this great library 👍
I have the following schema (abridged):
defmodule ClientApiConfig do
schema "client_api_config" do
polymorphic_embeds_one(:args,
types: [
legal_tracker: DataIngestion.LegalTracker.ApiArgs,
counsellink: DataIngestion.Counsellink.ApiArgs,
ebiller_mock: DataIngestion.Api.DummyArgs
],
on_replace: :update,
on_type_not_found: :changeset_error
)
end
end
Then in my HTML form, following the LiveView example I have:
<%= for args_form <- polymorphic_embed_inputs_for(f, :args) do %>
<%= hidden_inputs_for(args_form) %>
<%= case get_polymorphic_type(f, ClientApiConfig, :args) do %>
<% :counsellink -> %>
... inputs for counsellink
<% :legal_tracker -> %>
...inputs for legal_tracker
<% end %>
<% end %>
(sidenote, I think the LiveView example is wrong, it should be get_polymorphic_type(f, Reminder, :channel) and not get_polymorphic_type(channel_form, Reminder, :channel))
The above form works if I'm editing new data which already contains an :args embed. If however I want to edit a new record and I start from an empty %ClientApiConfig{}, no fields will be rendered because polymorphic_embed_inputs_for(f, :args) returns [] (there's no :args embed and therefore no :__type__ field in it, I guess).
How can I enforce a default type? I can do that with polymorphic_embed_inputs_for/4, but since I'm using LV, I thought I'm supposed to use polymorphic_embed_inputs_for/2. Or perhaps I should use the undocumented to_form/5?
Seems to me that polymorphic_embed_inputs_for/2 should be extended to accept a type parameter.
You should be able to initialize the changeset with a default type like this: %ClientApiConfig{args: %DataIngestion.LegalTracker.ApiArgs{}}
A polymorphic_embed_inputs_for(form, field, type) would be nice, but there is already another 3-arity variant. Although the variants that take a function as argument could be deprecated in my mind, since everything is moving towards Phoenix components and away from the old function-based HTML helpers.
You should be able to initialize the changeset with a default type like this: %ClientApiConfig{args: %DataIngestion.LegalTracker.ApiArgs{}}
True, but in my application (I didn't mention this to keep the example simple), when creating a new record, the user is supposed to select the polymorphic type from a dropdown. This means that the selection of the type happens after the changeset is initialized. I could of course react to changes in the dropdown value and rebuild a changeset with the right type for args, but in the end I found it simpler to just use to_form:
<%= for args_form <- to_form(f.source, f, :args, input_value(form, :dropdown), []) do %>
<% end %>
Not very elegant probably, but it gets the job done. Glad you kept to_form public 😃 !
As you said, a polymorphic_embed_inputs_for(form, field, type) or equivalent function would be nice.
Is there a full example of how to do this somewhere?
I've also run into the same problem and have gotten around it by adding an extra type field to my schema that is set using a dropdown. Is there a better way?