Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the selected options of a multiselect in Elm?

Tags:

I've seen what is required for a getting the selected index of a single select but I'm interested in getting all of the selected options from a multi select. I haven't been able to work out how to do this.

I've attempted the following but I suspect the Json decoder is failing. I'm not 100% sure of that though, because the decoding happens in the virtual dom code and any errors there are thrown away.

type Msg
= SetMultipleInts (List Int)

-- I'm not seeing the SetMultipleInts message when I click on the multiselect
view model =
    div []
        [ select (onSelect SetMultipleInts) (List.map myOption [1..4]) ]

myOption : Int -> Html Msg
myOption id =
    option [ value (toString id) ] [ text <| "Option " ++ (toString id) ]

-- I'm not seeing anything happen in the onchange
onMultiSelect : (List Int -> msg) -> List (Html.Attribute msg)
onMultiSelect msg =
    [ on "change" (Json.map msg targetSelectedOptions), multiple True ]

targetSelectedOptions : Json.Decoder (List Int)
targetSelectedOptions =
    Json.at [ "target", "selectedOptions" ] (Json.list (Json.at [ "value" ] Json.int))

Can I do this without having to use ports?

like image 589
Grassdog Avatar asked Oct 14 '16 13:10

Grassdog


1 Answers

The decoder fails because event.target.selectedOptions is not a javascript array. When you cannot use Json.Decode.list, you can use Json.Decode.keyValuePairs.

Here is the example how you can use it. You may want to change extractValues below depending on how you want to react to empty selection and such.

targetSelectedOptions : Json.Decoder (List String)
targetSelectedOptions =
  let
    maybeValues =
      Json.at [ "target", "selectedOptions" ]
        <| Json.keyValuePairs
        <| Json.maybe ("value" := Json.string)
    extractValues mv =
      Ok (List.filterMap snd mv)
  in Json.customDecoder maybeValues extractValues
like image 117
Tosh Avatar answered Oct 14 '22 04:10

Tosh