I want to render simple dropdown within my elm app with the following code but it's not working as expected. I want to keep union type Role in place and avoid using strings if it's possible.
What's the best way to work with dropdown in Elm? I didn't find any example yet.
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 ]
The onClick
handler doesn't really work with option
elements. You'll instead want to capture the change
event and look at the JSON targetValue
to see what was selected.
I would first remove the onClick
handler and instead set the option
tag's value
attribute:
viewOption : Role -> Html Msg
viewOption role =
option
[ value <| toString role ]
[ text <| toString role ]
Now you'll need a JSON Decoder that can take the event's targetValue
string and convert it to a 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)
Now you just need to add that to the select
change
event handler:
[ select
[ on "change" (Json.Decode.map SelectRole targetValueRoleDecoder)
]
[ viewOption None
, viewOption Admin
, viewOption User
]
The fact that we have to resort to strings is merely an artifact of having to translate values from DOM events into valid union types. You'll still want to keep Role
as a union type; you just have to create JSON decoders targeting each union type for now, since Elm does not (yet) support any kind of automatic String to Union Type function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With