我想使用以下代码在我的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 ]
答案 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函数。