HTML Number Form Inputs

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.

2 Likes

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)
2 Likes

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.

5 Likes

@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

3 Likes

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