Many-to-many and multiple_select: insert ok, edit fails

Hello,

I have two entities in a many-to-many relationship, Client and Service.

In the Client schema I have the relationship defined as:

 many_to_many :services, MyApp.Customers.Service, join_through: "client_service",
                                                on_delete: :delete_all,
                                                on_replace: :delete

And the form has the following line:

<%= multiple_select f, :services, Enum.map(@services, &({&1.name, &1.id})), class: "selectpicker" %>

When I submit the form for an insert, it works perfectly. However, when I try to open the edit page, I get the following error:

protocol Phoenix.HTML.Safe not implemented for #Ecto.Changeset<action: :replace, changes: %{}, errors: [], data: #MyApp.Customers.Service<>, valid?: true>

If I understood correctly, it is trying to use the changeset to fill the data in the muliple_select. I’m missing something?

I’m sure that that I preloaded all associations, but even reading the documentation I couldn’t figure it out :persevere:

1 Like

I’m running into this same error :confused:

Edit: I missed this part of the docs, this seems to fix the problem

When working with structs, associations and embeds, you will need to tell Phoenix how to extract the value out of the collection. For example, imagine user.roles is a list of %Role{} structs. You must call it as:

multiple_select(form, :roles, ["Admin": 1, "Power User": 2],
                selected: Enum.map(@user.roles, &(&1.id))

The :selected option will mark the given IDs as selected unless the form is being resubmitted. When resubmitted, it uses the form params as values.

2 Likes