I am attempting to use schemaless changesets with dynamic forms to collect data via a input wizard of sorts, and am having trouble understanding how to have the form object and template interact predictably.
I have different types of wizard questions - free text, guided (bounded) text, and multiple choice. After each question, I fetch the next question, look at its type, and build a form to accept the input of that question’s data:
defp reset_form(question) do
question_type = Map.get(question, "type")
case question_type do
"multiple_choice" ->
types = %{choice: :string}
{:ok,
{%{}, types}
|> Ecto.Changeset.cast(%{}, Map.keys(types))
|> to_form(as: :question)}
"free_text" ->
types = %{response: :string}
{:ok,
{%{}, types}
|> Ecto.Changeset.cast(%{}, Map.keys(types))
|> to_form(as: :question)}
"guided_text" ->
types =
question["variables"]
|> Enum.map(&variable_type_from_question/1)
|> Map.new()
|> IO.inspect()
{:ok,
{%{}, types}
|> Ecto.Changeset.cast(%{}, Map.keys(types))
|> to_form(as: :bubba)}
_ ->
{:error, "Question type not found: #{question_type}"}
end
end
In the heex, it looks like the following:
Multiple Choice:
<.form for={@form} phx-submit="wizard_submit">
<div class="my-4">
<%= for c <- choices_lens(@question) do %>
<%!-- <label for={id_lens(c)}>{text_lens(c)}</label> --%>
<.input
label={text_lens(c)}
id={id_lens(c)}
name="form[choice]"
type="radio"
value={id_lens(c)}
/>
<% end %>
</div>
<.button>Next</.button>
</.form>
Free text:
<div>
<.form for={@form} phx-submit="wizard_submit">
<div class="my-4">
<.input type="textarea" id="a" field={@form[:response]} />
</div>
<.button>Next</.button>
</.form>
</div>
"""
end
On submit, these are the outputs:
M/C: %{"form" => %{"choice" => "a"}}
Free Text: %{"bubba" => %{"response" => "kjhg"}}
Why does the first output show “form” => … instead of “question”? Also - my free text form does not reset if I have two free text questions in a row. I suspect that’s because the value in the form I’m pushing in as an initial condition is not being associated with the input field. How do I connect these?