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.






















