我想使用以下代码在我的 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 ]
最佳答案
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(还)不支持任何类型的自动字符串到联合类型功能。
关于drop-down-menu - 如何在 Elm lang 中使用选择(下拉)标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39371105/