I am trying to make a liveview form with complex validation. Below is an outline of what the form looks like on the page.
build a questionaire:
custom questions:
|text field| |delete button|
|text field| |delete button|
...
|"add" button|
prebuilt questions:
category 1:
|checkbox for selecting question|, question text
|checkbox for selecting question|, question text
...
category 2:
|checkbox for selecting question|, question text
|checkbox for selecting question|, question text
...
...
There needs to be a limit on the total number of questions on the questionaire. There also needs to be a limit on the total number of questions in each group. For instance, a maximum of 3 custom questions, a maximum of 2 category_1 questions, etc.
I tried to implement a proof of concept form using inputs_for and a schema that looks like this:
defmodule QuestionaireBuilderSchema do
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
embeds_one :questionaire, Questionaire do
embeds_many :custom_questions, CustomQuestion do
field :text, :string
end
embeds_many :category1_questions, Cat1Question, on_replace: :delete do
field :text, :string
field :selected, :boolean
end
embeds_many :category2_questions, Cat2Question, on_replace: :delete do
field :text, :string
field :selected, :boolean
end
end
end
def changeset(qbs, attrs) do
qbs
|> cast(attrs, [])
|> cast_embed(:questionaire, with: &questionaire_changeset/2)
|> custom_validation_max_total(:questionaire, max: 10)
end
def questionaire_changeset(questionaire, attrs) do
questionaire
|> cast(attrs, [])
|> cast_embed(:custom_questions, with: &custom_question_changeset/2)
|> cast_embed(:category1_questions, with: &cat_question_changeset/2)
|> cast_embed(:category2_questions, with: &cat_question_changeset/2)
|> custom_validate_num_selected(:custom_questions, max: 3, min: 0)
|> custom_validate_num_selected(:category1, max: 2, min: 1)
end
def custom_question_changeset(question, attrs) do
question
|> cast(attrs, [:text])
|> validate_required([:text])
end
def cat_question_changeset(question, attrs) do
question
|> cast(attrs, [:text, :selected])
end
end
but one issue was the ability to add, edit, and remove the custom questions. The beginning of the article below describes the issue I had and suggests using individual forms for each question:
That worked great but I’m not sure how to cleanly validate the whole questionnaire since the individual questions now have their own forms. I should mention that, despite the title of the article I linked, this is not a question about how to solve this problem while also implementing liveview streams (although that would be an interesting question on its own).
To summarize, I feel like I could figure out how to make it work as a single form or as one form per question(potentially with liveview streams as well). But I wonder if anyone has any suggestions on what path they would take.
For reference I am on the latest versions of phoenix(1.7) and liveview(0.20).