I've been following this tutorial: http://guide.elm-lang.org/architecture/user_input/forms.html
The text there makes sense to me, my question pertains to the exercise it lists at the bottom of the page. It asks that I:
"Add an additional field for age and check that it is a number."
I am having difficulty with this because the onInput
function seems to only accept a String input. I find it odd that there is no equivalent for type="number"
inputs.
Nevertheless, this is my attempt which does not work:
import Html exposing (..)
import Html.App as Html
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)
import String exposing (length)
main =
Html.beginnerProgram { model = model, view = view, update = update }
-- MODEL
type alias Model =
{ name : String
, password : String
, passwordAgain : String
, age : Int
}
model : Model
model =
Model "" "" "" 0
-- UPDATE
type Msg
= Name String
| Password String
| PasswordAgain String
| Age Int
update : Msg -> Model -> Model
update msg model =
case msg of
Name name ->
{ model | name = name }
Password password ->
{ model | password = password }
PasswordAgain password ->
{ model | passwordAgain = password }
Age age ->
{ model | age = age }
-- VIEW
view : Model -> Html Msg
view model =
div []
[ input [ type' "text", placeholder "Name", onInput Name ] []
, input [ type' "password", placeholder "Password", onInput Password ] []
, input [ type' "password", placeholder "Re-enter Password", onInput PasswordAgain ] []
, input [ type' "number", placeholder "Age", onInput Age ] []
, viewValidation model
]
viewValidation : Model -> Html msg
viewValidation model =
let
(color, message) =
if model.password /= model.passwordAgain then
("red", "Passwords do not match!")
else if length model.password <= 8 then
("red", "Password must be more than 8 characters!")
else
("green", "OK")
in
div [ style [("color", color)] ] [ text message ]
The error I get is the following:
-- TYPE MISMATCH ----------------------------------------------------- forms.elm
The argument to function `onInput` is causing a mismatch.
58| onInput Age
^^^
Function `onInput` is expecting the argument to be:
String -> a
But it is:
Int -> Msg
Note: I am aware that I could create the Age input as just another text input, but the exercise specifically asked me to check that it is a `number type. I assume this means I should hold it inside the model as an Int.
I am clear about what the error is. I simply want to know the idiomatic way to fix this in Elm. Thanks.
Any user-input from onInput
event is a String.
Your Model
expects it to be an Int
Use String.toInt to parse the integer value from a string value.
Adjust update
function to convert the type to an Int
and change the type signature to Age String
Age age ->
case String.toInt age of
Ok val ->
{ model | age = val }
-- Notify the user, or simply ignore the value
Err err ->
model
That way you have an option to notify the user about the error.
In case if Maybe
value suits you better, the whole statement can be simplified to:
Age age ->
{ model | age = Result.toMaybe (String.toInt age) }