robinvdvleuten
Adding class to date_select elements
How can I add a class to each select generated by date_select? I already created a custom builder but I can’t figure out how to add a class name to each select element;
builder = fn b ->
~e"""
<div class="flex">
<%= b.(:day, []) %>
<%= b.(:month, []) %>
<%= b.(:year, []) %>
</div>
"""
end
Thanks in advance for any help!
Most Liked Responses
voughtdq
builder = fn b ->
~e"""
<div class="flex">
<%= b.(:day, [class: "xyz"]) %>
<%= b.(:month, [class: "abc"]) %>
<%= b.(:year, [class: "def"]) %>
</div>
"""
end
peerreynders
Note to self - trying stuff out …
some_phoenix_project$ iex -S mix
Erlang/OTP 21 [erts-10.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]
Interactive Elixir (1.7.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> import Phoenix.HTML
Phoenix.HTML
iex(2)> import Phoenix.HTML.Form
Phoenix.HTML.Form
iex(3)> builder = fn select_for ->
...(3)> ~E"""
...(3)> <div class="flex">
...(3)> <%= select_for.(:day, [class: "xyz"]) %>
...(3)> <%= select_for.(:month, [class: "abc"]) %>
...(3)> <%= select_for.(:year, [class: "def"]) %>
...(3)> </div>
...(3)> """
...(3)> end
#Function<6.128620087/1 in :erl_eval.expr/5>
iex(4)> content = ~E"""
...(4)> <%= date_select :user, :born_at,
...(4)> builder: builder,
...(4)> year: [options: 2018..2018],
...(4)> month: [options: 12..12],
...(4)> day: [options: 13..13]
...(4)> %>
...(4)> """
{:safe,
[
[
"",
[
[
[
[
[
["" | "<div class=\"flex\">\n "],
60,
"select",
[
[32, "class", 61, 34, "xyz", 34],
[32, "id", 61, 34, "user_born_at_day", 34],
[32, "name", 61, 34, "user[born_at][day]", 34]
],
62,
[
"",
60,
"option",
[[32, "value", 61, 34, "13", 34]],
62,
"13",
60,
47,
"option",
62
],
60,
47,
"select",
62
] |
"\n "
],
60,
"select",
[
[32, "class", 61, 34, "abc", 34],
[32, "id", 61, 34, "user_born_at_month", 34],
[32, "name", 61, 34, "user[born_at][month]", 34]
],
62,
[
"",
60,
"option",
[[32, "value", 61, 34, "12", 34]],
62,
"12",
60,
47,
"option",
62
],
60,
47,
"select",
62
] |
"\n "
],
60,
"select",
[
[32, "class", 61, 34, "def", 34],
[32, "id", 61, 34, "user_born_at_year", 34],
[32, "name", 61, 34, "user[born_at][year]", 34]
],
62,
[
"",
60,
"option",
[[32, "value", 61, 34, "2018", 34]],
62,
"2018",
60,
47,
"option",
62
],
60,
47,
"select",
62
] |
"\n</div>\n"
] |
"\n"
]}
iex(5)> safe_to_string(content)
"<div class=\"flex\">\n <select class=\"xyz\" id=\"user_born_at_day\" name=\"user[born_at][day]\"><option value=\"13\">13</option></select>\n <select class=\"abc\" id=\"user_born_at_month\" name=\"user[born_at][month]\"><option value=\"12\">12</option></select>\n <select class=\"def\" id=\"user_born_at_year\" name=\"user[born_at][year]\"><option value=\"2018\">2018</option></select>\n</div>\n\n"
iex(6)>
peerreynders
You provided this as your reference case:
My purpose was to attempt to generate equivalent HTML output with a builder function.
So if we start out with (in iex):
import Phoenix.HTML
import Phoenix.HTML.Form
default_date = {2020, 12, 25}
content =
~E"""
<%= date_select :user, :date, default: default_date %>
"""
safe_to_string(content)
We’ll get this output:
<select id=\"user_date_year\" name=\"user[date][year]\">
<option value=\"2014\">2014</option>
<option value=\"2015\">2015</option>
<option value=\"2016\">2016</option>
<option value=\"2017\">2017</option>
<option value=\"2018\">2018</option>
<option value=\"2019\">2019</option>
<option value=\"2020\" selected>2020</option>
<option value=\"2021\">2021</option>
<option value=\"2022\">2022</option>
<option value=\"2023\">2023</option>
<option value=\"2024\">2024</option>
</select> /
<select id=\"user_date_month\" name=\"user[date][month]\">
<option value=\"1\">January</option>
<option value=\"2\">February</option>
<option value=\"3\">March</option>
<option value=\"4\">April</option>
<option value=\"5\">May</option>
<option value=\"6\">June</option>
<option value=\"7\">July</option>
<option value=\"8\">August</option>
<option value=\"9\">September</option>
<option value=\"10\">October</option>
<option value=\"11\">November</option>
<option value=\"12\" selected>December</option>
</select> /
<select id=\"user_date_day\" name=\"user[date][day]\">
<option value=\"1\">01</option>
<option value=\"2\">02</option>
<option value=\"3\">03</option>
<option value=\"4\">04</option>
<option value=\"5\">05</option>
<option value=\"6\">06</option>
<option value=\"7\">07</option>
<option value=\"8\">08</option>
<option value=\"9\">09</option>
<option value=\"10\">10</option>
<option value=\"11\">11</option>
<option value=\"12\">12</option>
<option value=\"13\">13</option>
<option value=\"14\">14</option>
<option value=\"15\">15</option>
<option value=\"16\">16</option>
<option value=\"17\">17</option>
<option value=\"18\">18</option>
<option value=\"19\">19</option>
<option value=\"20\">20</option>
<option value=\"21\">21</option>
<option value=\"22\">22</option>
<option value=\"23\">23</option>
<option value=\"24\">24</option>
<option value=\"25\" selected>25</option>
<option value=\"26\">26</option>
<option value=\"27\">27</option>
<option value=\"28\">28</option>
<option value=\"29\">29</option>
<option value=\"30\">30</option>
<option value=\"31\">31</option>
</select>\n"
Note how the “2020”, “12” and “25” option elements have the selected attribute.
Now a builder version:
import Phoenix.HTML
import Phoenix.HTML.Form
make_builder = fn {year, month, day} ->
fn b ->
~E"""
<%= b.(:year, [value: year, options: 2014..2024, class: "def"]) %> / <%= b.(:month, [value: month]) %> / <%= b.(:day, [value: day]) %>
"""
end
end
default_date = {2020, 12, 25}
builder = make_builder.(default_date)
content =
~E"""
<%= date_select :user, :date, builder: builder %>
"""
safe_to_string(content)
which produces the same output.
EDIT:
Now having seen this code:
https://github.com/phoenixframework/phoenix_html/blob/v2.13.0/lib/phoenix_html/form.ex#L1391-L1395
This works as expected:
import Phoenix.HTML
import Phoenix.HTML.Form
builder =
fn b ->
~E"""
<%= b.(:year, [options: 2014..2024, class: "def"]) %> / <%= b.(:month, []) %> / <%= b.(:day, []) %>
"""
end
default_date = {2020, 12, 25}
content =
~E"""
<%= date_select :user, :date, builder: builder, default: default_date %>
"""
safe_to_string(content)
If you look at the date_select code it should become obvious that the :default value has already been extracted and is being handed to the builder function as the value to format.
By the time builder runs it’s too late to influence the :default because
value = Keyword.get(opts, :value, input_value(form, field) || Keyword.get(opts, :default))
has already happened.








