如何在Elm lang中使用select(下拉)标签

时间:2016-09-07 13:22:25

标签: drop-down-menu html-select dropdown elm

我想使用以下代码在我的elm应用程序中呈现简单的下拉列表,但它没有按预期工作。我希望保持联合类型角色,并避免在可能的情况下使用字符串。

使用Elm下拉菜单的最佳方法是什么?我还没有找到任何例子。

import Html exposing (..)
import Html.App exposing (beginnerProgram)
import Html.Events exposing (..)
import Html.Attributes exposing (..)
import Json.Decode

main =
  beginnerProgram
    { model = initialModel
    , view = view
    , update = update
    }

initialModel =
  { role = None
  }

type Role
  = None
  | Admin
  | User

type alias Model = 
  { role: Role
  }

type Msg
  = SelectRole Role


update msg model =
  case msg of
    SelectRole role ->
      { model | role = role }


view : Model -> Html Msg
view model =
  div
    []
    [ select
        [ ]
        [ viewOption None
        , viewOption Admin
        , viewOption User
        ]
    , pre [] [ text <| toString model ]
    ]



viewOption : Role -> Html Msg
viewOption role =
  option
    [ onClick (SelectRole role) ]
    [ text <| toString role ]

1 个答案:

答案 0 :(得分:8)

onClick处理程序与option元素无关。您反而希望捕获change事件并查看JSON targetValue以查看所选内容。

我首先删除onClick处理程序,然后设置option代码value属性:

viewOption : Role -> Html Msg
viewOption role =
  option
    [ value <| toString role ]
    [ text <| toString role ]

现在您需要一个JSON解码器,可以接收事件的targetValue字符串并将其转换为Role

targetValueRoleDecoder : Json.Decode.Decoder Role
targetValueRoleDecoder =
  targetValue `Json.Decode.andThen` \val ->
    case val of
      "Admin" -> Json.Decode.succeed Admin
      "User" -> Json.Decode.succeed User
      "None" -> Json.Decode.succeed None
      _ -> Json.Decode.fail ("Invalid Role: " ++ val)

现在您只需将其添加到select change事件处理程序:

    [ select
        [ on "change" (Json.Decode.map SelectRole targetValueRoleDecoder)
        ]
        [ viewOption None
        , viewOption Admin
        , viewOption User
        ]

我们必须求助于字符串的事实仅仅是必须将DOM事件中的值转换为有效的联合类型的工件。您仍然希望将Role保留为联合类型;你现在必须创建针对每种联合类型的JSON解码器,因为Elm(还)不支持任何类型的自动String到Union Type函数。