I’m creating a Phoenix LiveView application where a user can create an interview and add questions to that interview. I have a one-to-many relationship so that one interview can have many questions. There will always be at least one question, but otherwise it is up to the user how many questions they add.
I’m using inputs_for
so that when creating/editing an interview you can change the questions for it. You can what the form looks like here
Because it’s up to the user how many questions an interview has there’s an ‘Add Question’ button. This adds another input, like so:
Currently to get the repeating inputs to show, I’ve been adding a new question to changeset.changes.questions
.
The problem that I’m running in to is, if we modify the text for the first question, and then press ‘Add Question’, I can’t simply update changeset.changes.questions
to equal changeset.data.questions ++ [%Interviewing.Interviews.Question{}]
because it will lose any of the existing changes.
The opposite is also true, I can’t do changeset.changes.questions ++ [%Interviewing.Interviews.Question{}]
if we’re editing an existing interview and we go straight to adding a question, as there are no existing changes and changeset.changes.questions
does not exist.
So far I’ve created a utility get_changeset_existing_questions
which will either get changeset.changes.questions
, or if it does not existing create a list of ignored changes based on the existing questions in the changeset data.
defp get_changeset_existing_questions(changeset) do
Map.get(
changeset.changes,
:questions,
Enum.map(changeset.data.questions, &%{change(&1) | action: :ignore})
)
end
def add_question_to_changeset(changeset) do
new_question = %Interviewing.Interviews.Question{}
new_question_changeset = change(new_question)
questions_changeset = get_changeset_existing_questions(changeset) ++ [new_question_changeset]
Map.put(changeset, :changes, Map.merge(changeset.changes, %{questions: questions_changeset}))
end
I’m not convinced by the correctness of what I’m doing, is there a better way? Should I simply apply any of the existing changes before adding a new change, so that I can always do changeset.data.questions ++ [%Interviewing.Interviews.Question{}]
? Can I update the data directly when adding a new question and ignore changeset.changes
completely? Am I missing an obvious function from Ecto.Changeset? Is my entire approach wrong?
Any help would be appreciated, thanks!