Radio buttons and Elm

While working on a project with Elm, I needed to include some radio buttons in a Elm generated form. While there is a great example on how to create forms with text inputs in Elm, I couldn’t seem to find examples or documentation on how to handle radio buttons.

Let’s start with setting up the basic skeleton for our simple app.

import Html (..) import Html.Attributes (..) import Html.Events (..) import Signal (..) -- MODELS type alias Model = { radio : String } type Update = NoOp | Checked String initialModel : Model initialModel = { radio = "y" } -- UPDATE update : Update -> Model -> Model update upd model = case upd of NoOp -> model Checked selection -> { model | radio <- selection } -- VIEW view : Model -> Html view model = div [ ] [ text ("You selected: " ++ model.radio) , yesNoField "yesorno" Checked ] yesNoField : String -> (String -> Update) -> Html yesNoField fieldName toUpdate = div [ ] [ div [ ] [ input [ type' "radio" , name fieldName , value "y" ] [ ] , text "Yes" ] , div [ ] [ input [ type' "radio" , name fieldName , value "n" ] [ ] , text "No" ] ] -- SIGNALS model : Signal Model model = foldp update initialModel (subscribe updateChannel) updateChannel : Channel Update updateChannel = channel NoOp -- MAIN main : Signal Html main = view <~ model

Going by the form example, we should now add a on event to the input fields in the yesNoField .

input [ type' "radio" , name fieldName , value "y" , on "input" targetValue (send updateChannel << toUpdate) ]

However, it seems that the first argument to on is some kind of event name. This is the correct one when using normal textual input fields, but it doesn’t work with radio buttons.

When faced with this problem, I started looking for other examples with radio buttons or some documentation on what this event name variable could be. Unfortunately I couldn’t find anything. So I decided to dive into some of the compiled Elm code to try and figure out what it should be.

To do this I compiled Radio.elm with elm-make and wrote a simple index.html to manually embed the elm.js source code and run it.

The source code for the on function shows that it is nothing more than the VirtualDom.on function. This on function is apparently just returning a property, that will be added to the proper HTML tag by Elm, so we need to dig a little deeper.

By searching through the source code on delegator , I stumbled upon the interesting looking createHandler and findAndInvokeListeners functions. By adding console.log(eventName); at the top of findAndInvokeListeners I got some interesting output

mousedown focus focusIn mouseup change click

I figured change was the way to go. So let’s try it. Change yesNoField to

yesNoField : String -> (String -> Update) -> Html yesNoField fieldName toUpdate = div [ ] [ div [ ] [ input [ type' "radio" , name fieldName , value "y" , on "change" targetValue (send updateChannel << toUpdate) ] [ ] , text "Yes" ] , div [ ] [ input [ type' "radio" , name fieldName , value "n" , on "change" targetValue (send updateChannel << toUpdate) ] [ ] , text "No" ] ]

When you recompile and refresh, everything should be working.

Conclusion

Is it difficult to get radio buttons working in Elm? No. You just need to add the on "change" targetValue someMessage attribute to your input and wire up this message like you would do with any other messages.