How to POST empty <select .. multiple> HTML elements if empty?

I have a multiple_select and I would like to being able to send an empty list.

This:

<select id="user_roles" name="user[roles][]">
    <option value="1" selected="selected">Admin</option>
    <option value="2">Power User</option>
</select>

gives %{user: %{roles: [1]}}.

But there is no way to get: %{user: %{roles: []}} as an empty list.

This SO question suggests to add a hidden field before, so I tried:

<input type="hidden" name="user[roles][]" value="" />
<select id="user_roles" name="user[roles][]">
    <option value="1" selected="selected">Admin</option>
    <option value="2">Power User</option>
</select>

but it gives: %{user: %{roles: [""]}}, which is not what I’d expect.

<input type="hidden" name="user[roles]" value="" />
<select id="user_roles" name="user[roles][]">
    <option value="1" selected="selected">Admin</option>
    <option value="2">Power User</option>
</select>

but it gives: %{user: %{roles: nil}}, which is better, but still not exactly what I need.

Is there a way to get empty array value?

Cheers

There is no way to get an empty list. Either there is an entry to the list and therefore it’s not empty anymore or there’s not, but nobody knows there was supposed to be a list in the first place. This essentially comes down to how application/x-www-form-urlencoded works and how elixir values are derived from it.

If you handle your params with Ecto.Changeset.cast/4, by initializing your roles field to [], instead of nil by default, are you able to get the result you are looking for?

You still can deal with this when you handle your params (for example by a Map.get(user_params, "roles", [])).

@LostKobrakai yup there doesn’t seem to be a standard way to handle this at the application/x-www-form-urlencoded level. :disappointed:

It could have been that Phoenix did propose an extra behavior on top of it.

Like <input type="hidden" name="user[roles]" value="[]" />, which could be parsed into %{user: %{roles: []}} instead of %{user: %{roles: "[]"}}.

@t0t0 yes, I did add a behavior that transforms the nil value into [], but I would expect this to be done at framework level instead of app one.

Never mind, it does the job.

To be fair, phoenix cannot know if you actually want to deal with nil. It’s not like replacing it with [] is the definitive correct way of handling things.