I’ve seen a few varying answers, but I’m wondering if there is a best (or accepted) way to use number
inputs in forms. The onInput
event always returns a string.
You can use String.toInt
and then do something with the Result
. Looking at some of my old code, I had a similar case; I ended up defining a helper and then using it like this.
But in general, if you have a reasonable default…
type Msg = HandleInput Int
handleInput : Attribute Msg
handleInput =
onInput (HandleInput << Result.withDefault 0 << String.toInt)
We use String
in our form model for this. Then parse that at the very end for validation and sending to the BE.
The reason is that working with numbers is harder if you want to allow decimals. e.g. user types 0.
, then the decoder removes the .
and the user can’t type a decimal.
We found that it is easier to deal with number inputs by adding type="number"
to the input and letting the model be a String.
@mthadley That does seem to be the clearest way. As far as I can tell though, like @Sebastian noted, it doesn’t work as well for non-integer (float) values. Did you ever try it with that and have a solution?
@Sebastian Do you happen to have an example of the best way to do validation in that case?
Here I made an example https://ellie-app.com/djZX9DPkYa1/1
I always use Strings to store form values in my model, because that is what they are. Then at certain times I attempt to parse and normalize the string, such as the blur event or form submit.
Sometimes I don’t even bother because the API has to do that anyway, and I can show what was actually persisted after I get a response back. Works for simpler CRUD apps.
I do sometimes use event handlers on the form fields to directly filter key presses. Elm is currently bad at this, so I do it using jQuery event delegation (I know I know).
No, I only ever needed Int
values, so the above worked for me. Sounds like a String
might work better for you.
I have a type that can take an Int and a String, so I plug onInput
to the String version, and run String.toInt onBlur