diff --git a/README.md b/README.md index 1ae5dea..db181fc 100644 --- a/README.md +++ b/README.md @@ -224,7 +224,7 @@ They both render a hidden input for the `"__type__"` field. ### Displaying form inputs and errors in LiveView -You may use `polymorphic_embed_inputs_for/2` when working with LiveView. +You may use `PolymorphicEmbed.HTML.Component.polymorphic_embed_inputs_for/1` when working with LiveView, which functions similarly to [`Phoenix.Component.inputs_for/1`](Phoenix.Component.inputs_for). ```elixir <.form @@ -234,26 +234,18 @@ You may use `polymorphic_embed_inputs_for/2` when working with LiveView. phx-change="validate" phx-submit="save" > - <%= for channel_form <- polymorphic_embed_inputs_for f, :channel do %> - <%= hidden_inputs_for(channel_form) %> + <.polymorphic_embed_inputs_for field={f[:channel]} :let={channel_form}> + <%= case source_module(channel_form) do %> + <% SMS -> %> + <.input field={channel_form[:number]} label="Number" /> - <%= case get_polymorphic_type(f, :channel) do %> - <% :sms -> %> - <%= label channel_form, :number %> - <%= text_input channel_form, :number %> - - <% :email -> %> - <%= label channel_form, :email_address %> - <%= text_input channel_form, :adress %> + <% Email -> %> + <.input field={channel_form[:address]} label="Email Address" /> <% end %> - <% end %> + ``` -Using this function, you have to render the necessary hidden inputs manually as shown above. - -There is also `PolymorphicEmbed.HTML.Component.polymorphic_embed_inputs_for/1`, which functions similarly to [`Phoenix.Component.inputs_for/1`](Phoenix.Component.inputs_for). - ### Get the type of a polymorphic embed Sometimes you need to serialize the polymorphic embed and, once in the front-end, need to distinguish them. diff --git a/lib/polymorphic_embed/html/form.ex b/lib/polymorphic_embed/html/form.ex index 0c6ef10..e2c1697 100644 --- a/lib/polymorphic_embed/html/form.ex +++ b/lib/polymorphic_embed/html/form.ex @@ -6,6 +6,12 @@ if Code.ensure_loaded?(Phoenix.HTML) && Code.ensure_loaded?(Phoenix.HTML.Form) & defdelegate get_polymorphic_type(form, field), to: PolymorphicEmbed.HTML.Helpers + defdelegate get_polymorphic_type(form_field), to: PolymorphicEmbed.HTML.Helpers + + defdelegate source_data(form), to: PolymorphicEmbed.HTML.Helpers + + defdelegate source_module(form), to: PolymorphicEmbed.HTML.Helpers + defdelegate to_form(source_changeset, form, field, options), to: PolymorphicEmbed.HTML.Helpers diff --git a/lib/polymorphic_embed/html/helpers.ex b/lib/polymorphic_embed/html/helpers.ex index dd848ff..cd8b60e 100644 --- a/lib/polymorphic_embed/html/helpers.ex +++ b/lib/polymorphic_embed/html/helpers.ex @@ -30,6 +30,25 @@ if Code.ensure_loaded?(Phoenix.HTML) && Code.ensure_loaded?(Phoenix.HTML.Form) d end end + def get_polymorphic_type(%Phoenix.HTML.FormField{} = form_field) do + %{field: field_name, form: parent_form} = form_field + get_polymorphic_type(parent_form, field_name) + end + + @doc """ + Returns the source data structure + """ + def source_data(%Phoenix.HTML.Form{} = form) do + form.source.data + end + + @doc """ + Returns the source data structure + """ + def source_module(%Phoenix.HTML.Form{} = form) do + form.source.data.__struct__ + end + def to_form(%{action: parent_action} = source_changeset, form, field, options) do id = to_string(form.id <> "_#{field}") name = to_string(form.name <> "[#{field}]") diff --git a/test/polymorphic_embed_test.exs b/test/polymorphic_embed_test.exs index 1c7ed42..3352644 100644 --- a/test/polymorphic_embed_test.exs +++ b/test/polymorphic_embed_test.exs @@ -3124,6 +3124,53 @@ defmodule PolymorphicEmbedTest do end end + test "Form.source_data/1 and Form.source_module/1" do + reminder_module = get_module(Reminder, :polymorphic) + + attrs = %{ + date: ~U[2020-05-28 02:57:19Z], + text: "This is an Email reminder", + contexts: [ + %{ + __type__: "device", + ref: "12345", + type: "cellphone" + }, + %{ + __type__: "location", + age: "aquarius", + address: "some address" + } + ] + } + + changeset = + reminder_module + |> struct() + |> reminder_module.changeset(attrs) + + safe_form_for(changeset, fn _f -> + safe_inputs_for(changeset, :contexts, :email, :polymorphic_with_type, fn f -> + PolymorphicEmbed.HTML.Form.get_polymorphic_type(f[:contexts]) + + case PolymorphicEmbed.HTML.Form.source_data(f) do + %PolymorphicEmbed.Reminder.Context.Device{} -> + assert PolymorphicEmbed.Reminder.Context.Device == PolymorphicEmbed.HTML.Form.source_module(f) + + %PolymorphicEmbed.Reminder.Context.Location{} -> + assert PolymorphicEmbed.Reminder.Context.Location == PolymorphicEmbed.HTML.Form.source_module(f) + + _ -> + assert false + end + + 1 + end) + + 1 + end) + end + describe "Form.get_polymorphic_type/3" do test "returns type from changeset via identify_by_fields" do reminder_module = get_module(Reminder, :polymorphic)