How can I add "disabled" attribute to a Phoenix.HTML.Form select prompt option?

I’m using materialize_css as view style in my templates.
So I would like to generate something like this:

<select class="" id="form_choice" name="form[choice]">
    <option value="" disabled selected>Choose a color</option>
    <option value="white">white</option>
    <option value="black">black</option>
    <option value="gray">gray</option>
</select>

but I’m not finding where I could add the attribute “disabled” for the option set with “prompt” key.

Please, how can I transform something like
select :form, :choice, [:white, :black, :gray], prompt: "Choose a color"
to have the attribute “disabled” set on the prompt option ?

In the docs I see I can use with select, options such as :key, :value, :disabled but it does not work for the prompt option.

Here’s an example from the docs:

select(form, :role, [[key: "Admin", value: "admin", disabled: true],
                     [key: "User", value: "user"]])
#=> <select id="user_role" name="user[role]">
    <option value="admin" disabled="disabled">Admin</option>
    <option value="user">User</option>
    </select>

https://hexdocs.pm/phoenix_html/Phoenix.HTML.Form.html#select/4

Generates a select tag with the given options .

options are expected to be an enumerable which will be used to generate each respective option . The enumerable may have:

  • keyword lists - each keyword list is expected to have the keys :key and :value . Additional keys such as :disabled may be given to customize the option
5 Likes

Not sure if I understand you correctly, you want a disabled option that is selected by default, right? AFAIK you cannot select a disabled <option>, but that is a HTML thing. However you can use a few tricks by using JavaScript or just CSS, here is a simple one:

<%
  select :form, :choice,
  [[key: "Choose a color", value: "", style: "display: none;"],
  [key: "White", value: "white"],
  [key: "Black", value: "black"],
  [key: "Gray", value: "gray"]]
%>

Disabling the default option is usually done to force the user to select a different option. It’s kinda like setting required on input fields.

2 Likes

Yes I understand I can use a collection like:

[
    [key: "Choose a color", value: "", disabled: true],
    [key: "White", value: "white"]
    [key: "Black", value: "black"]
    [key: "Gray", value: "gray"]
]

This is a bit more verbose than passing the prompt text as I did it before, but it is okay with most of the use cases.
Unfortunately when using the form helper select/4 to generate optgroups the prompt text can not be set like that.

I think for now I will be using javascript and css to add the “disabled” attribute to the prompt text, when needed.

I think taking a look at Materialize select will help understand why I’m willing to add a “disabled” attribute to the prompt text. The link shows well the effect.

@Gazler
Thank you, finally I managed the options to work even with optgroups. Probably I was passing wrong keyword list to the select/4 helper.

Now I can use something like:

[
  [key: "Choose a color", value: "", disabled: true],
  set1: [
    [key: "White", value: "white"],
    [key: "Black", value: "black"],
    [key: "Gray", value: "gray"]
  ],
  set2: [
    [key: "Blue", value: "blue"],
    [key: "Red", value: "red"],
    [key: "Green", value: "green"]
  ]
]

or even shorter :slight_smile:

[
  [key: "Choose a color", value: "", disabled: true],
  set1: [:white, :black, :gray],
  set2: [:blue, :red, :green]
]

And with the following function I’m able able to better automate the whole thing. ^^

def collection(options, prompt \\ "Please choose an option", disabled \\ true),
    do: [[key: prompt, value: "", disabled: disabled]] |> Enum.concat(options)

The param “options” can be anything I would pass as options to select/4

2 Likes