Multiple_select problem when passing values in edit mode on a form

I have a form that allows you to create and edit a Student with multiple Skills. It uses a multiple_select and looks like this:
<%= multiple_select f, :skills, @skills, prompt: "Choose skills", selected: Enum.map(@student.skills, &(&1.id)) %>
This works perfectly fine when you are Editing a student, but it doesn’t work when you are Creating a New Student. The error it gives me is that student doesn’t exist in the template, which makes sense because I haven’t created a student yet.

What is the proper way to handle this? The documentation doesn’t seem to cover this. Should there be multiple forms or should I be doing some kind of conditional in the multiple_select?

Any guidance is greatly appreciated!

:wave:

What’s the exact error message? Maybe you need to pre-populate the student struct with empty list for skills and assign it to the socket?

def new_student do
  %Student{skills: []}
end
2 Likes

I assume you have an action in your controller:

def new(conn, _params) do
  changeset = MyContext.change_form(%Student{})
  skills = MyContext.list_skills()
  render(conn, "new.html", changeset: changeset, skills: skills)
end

And you have a form definition in *html.eex template similar to:

<%= form_for @changeset, @action, [], fn f -> %>

So, you need to change your code like this:

<%= multiple_select f, :skills, @skills, 
  prompt: "Choose skills", 
  selected: Enum.map(@changeset.data.skills, &(&1.id)) %>
2 Likes

It is also accessible via f.data.skills :slight_smile:

2 Likes

This makes sense. I should have more thoroughly examined the changeset. I’m very new to Elixir and Phoenix and just didn’t expect it to work correctly for some reason.

I had actually worked out a temporary workaround by doing some work in the View that looked like this.

def get_selected_skills(conn) do
  if Map.has_key?(conn.assigns, :student) do
    Enum.map(conn.assigns.student.skills, &(&1.id))
  else
    []
  end
end

Your method obviously makes a lot more sense. Thanks again for the help!

1 Like