扩展Elm教程表单应用程序以包含编号输入Age

时间:2016-08-16 18:18:12

标签: elm

我一直在关注本教程:http://guide.elm-lang.org/architecture/user_input/forms.html

那里的文字对我有意义,我的问题与它在页面底部列出的练习有关。它问我:

  

“为年龄添加其他字段并检查它是否为数字。”

我遇到这个问题很困难,因为onInput函数似乎只接受String输入。我觉得很奇怪,type="number"输入没有等价物。

然而,这是我的尝试不起作用:

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 ]

我得到的错误如下:

-- 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

注意:我知道我可以创建Age输入作为另一个文本输入,但练习特别要求我检查它是一个`数字类型。我认为这意味着我应该把它作为Int。

保存在模型中

我很清楚错误是什么。我只是想知道在Elm中解决这个问题的惯用方法。感谢。

2 个答案:

答案 0 :(得分:6)

来自onInput事件的任何用户输入都是字符串。

您的Model期望它是Int

使用String.toInt从字符串值中解析整数值。

调整update功能,将类型转换为Int,并将类型签名更改为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

通过这种方式,您可以选择通知用户错误。

如果Maybe值更适合您,整个陈述可以简化为:

Age age ->
    { model | age =  Result.toMaybe (String.toInt age) }

答案 1 :(得分:1)

你需要相当于onInput,但对于整数运算。根据{{​​1}}的定义方式,您可以通过添加targetValue来执行类似的操作,将其解析为整数:

Json.Decode.int

然后您可以这样使用它:

onIntInput : (Int -> msg) -> Attribute msg
onIntInput tagger =
  Html.Events.on "input" (Json.map tagger (Json.at ["target", "value"] Json.int))