Hey all!
Hope you are doing well
We are using the new phx 1.7 core components, and the attributes handling of the checkbox one is disturbing to me.
The source code of the entire <.input type="checkbox">
component is available here.
The thing that bothering me the most, is the mixing of the checked
and the value
attribute:
def input(%{type: "checkbox", value: value} = assigns) do
assigns =
assign_new(assigns, :checked, fn -> Phoenix.HTML.Form.normalize_value("checkbox", value) end)
In raw html, the value
attribute is expected to be a string, and to be the value sent when the form is submitted. It can be any string.
But here, it is expected to be a boolean string ie. "true"
to act as checked. Any other string, and the checked is false (that’s the point of Phoenix.HTML.Form.normalize_value/2
). The checked=
attribute, is still expected to be a boolean.
Furthermore, the value=""
attributes are hard coded in the component as boolean strings:
<input type="hidden" name={@name} value="false" />
<input
[…]
value="true"
checked={@checked}
/>
So first of all, I find the value
attribute very disturbing, since it’s not at all the same logic as the raw html. Note that I understand that we can drift from the raw html specs, but the vast majority of the core components are really close from the html specs.
Then, the value=
is in fact pretty useless, since it’s used only as a default for checked=
. But, by having it in the def pattern matching, it is de facto required even if unused by the component itself, or face the runtime error (cannot be catch at compile time I reckon sinc the attr
macro is used for all the variations of def input
).
I understand that having the value
attr set as a boolean string is probably handy for reloading the form after submission though, and it may be the root reason for this design, I don’t know.
To sum up:
-
The behavior of
<.input type="checkbox">
is in fact really different from native html, I find it misleading:- Type mismatch of the value attribute (bool string vs any string)
- Different usage (checked vs checkbox actual value when checked)
- Can’t set an other actual value than a boolean
-
The implementation is quite frustratring since it forces me to use an attr I don’t want.
-
<input type="checkbox checked={true} />
raises for no functional reason
-
I’m not sure how things could be better…
For the first point, maybe renaming the input type in <input type="boolean" />
could be less misleading, and keeping the type="checkbox"
acting closer than the html specs? At least, it would assume creating a component that is not from the html specs.
For the second point, something like this would allow at least to not de facto require the value=
attribute:
def input(%{type: "checkbox"} = assigns) do
assigns =
assign_new(assigns, :checked, fn -> Phoenix.HTML.Form.normalize_value("checkbox", assigns[:value] || false) end)
I don’t know if I am missing something?