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

ond*_*rej 5 html-select drop-down-menu elm dropdown

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

使用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 ]
Run Code Online (Sandbox Code Playgroud)

Cha*_*ert 9

onClick处理器并没有真正一起工作option的元素.相反,您需要捕获change事件并查看JSON targetValue以查看所选内容.

我先删除onClick处理程序,然后设置option标记的value属性:

viewOption : Role -> Html Msg
viewOption role =
  option
    [ value <| toString role ]
    [ text <| toString role ]
Run Code Online (Sandbox Code Playgroud)

现在你需要一个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)
Run Code Online (Sandbox Code Playgroud)

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

    [ select
        [ on "change" (Json.Decode.map SelectRole targetValueRoleDecoder)
        ]
        [ viewOption None
        , viewOption Admin
        , viewOption User
        ]
Run Code Online (Sandbox Code Playgroud)

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