如何在 Elm 中获取多选的选定选项?

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

我看过 ,但我有兴趣从多 select 中获取所有 selected 选项。我还没弄明白该怎么做。

我尝试了以下操作,但我怀疑 Json 解码器出现故障。不过我不是 100% 确定这一点,因为解码发生在虚拟 dom 代码中,任何错误都会被丢弃。

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))

我可以在不使用端口的情况下执行此操作吗?

解码器失败,因为 event.target.selectedOptions 不是 javascript数组。当你不能使用 Json.Decode.list 时,你 可以使用 Json.Decode.keyValuePairs.

这是您如何使用它的示例。 您可能需要根据以下情况更改 extractValues 关于您想如何对空选择等做出反应。

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

如果有人需要在 Elm 中进行多选,我在 Elm 0.19 中重写了一个完整的示例:

https://ellie-app.com/g7WrS9cV4zVa1

module Main exposing (main)

import Browser
import Html exposing (..)
import Html.Attributes
import Html.Events
import Json.Decode


type alias Model =
    { value : List ( String, Maybe String ) }


init : Model
init =
    { value = [] }


type Msg
    = SetMultipleInts (List ( String, Maybe String ))


update : Msg -> Model -> Model
update msg model =
    case msg of
        SetMultipleInts value ->
            { model | value = value }


view : Model -> Html Msg
view model =
    div []
        [ select
            [ Html.Events.on "change"
                (Json.Decode.map SetMultipleInts targetSelectedOptions)
            , Html.Attributes.multiple True
            ]
            (List.map myOption (List.range 1 4))
        , div []
            [ text <|
                Debug.toString
                    (model
                        |> .value
                        |> List.map Tuple.second
                        |> List.filterMap identity
                    )
            ]
        ]


targetSelectedOptions : Json.Decode.Decoder (List ( String, Maybe String ))
targetSelectedOptions =
    Json.Decode.at [ "target", "selectedOptions" ] <|
        Json.Decode.keyValuePairs <|
            Json.Decode.maybe (Json.Decode.at [ "value" ] Json.Decode.string)


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


main : Program () Model Msg
main =
    Browser.sandbox
        { init = init
        , view = view
        , update = update
        }