【问题标题】:Work with elm and select使用 elm 并选择
【发布时间】:2016-05-22 16:01:07
【问题描述】:

我试图通过一个自定义示例了解 elm 是如何工作的。

durationOption duration =
  option [value (toString duration) ] [ text (toString duration)]

view : Model -> Html Msg
view model =
  Html.div []
    [ h2 [] [ text "Month selector"]
    , select []
      (List.map durationOption [1..12])    
    ]

这是一个使用选择的简单示例。我想,例如,每次更改月份值时,它都会乘以 10。根据文档,没有像onChangeonSelect 这样的事件,我必须用on 创建我的吗?

【问题讨论】:

    标签: elm


    【解决方案1】:

    供 Elm 新手(如我)将来参考:使用 Elm 0.18.0 + elm-lang/html 2.0.0,onInput 事件(见下面的代码)works。 (还要注意 int 范围表示法的区别(List.range 0 12 而不是 [0..12])。

    import Html exposing (..)
    import Html.Attributes exposing (..)
    import Html.Events exposing (onInput)
    
    
    main =
      Html.beginnerProgram
        { model = model
        , view = view
        , update = update
        }
    
    
    
    -- MODEL
    
    
    type alias Model =
      { duration : Int
      }
    
    
    model : Model
    model =
      Model 0
    
    
    
    -- UPDATE
    
    
    type Msg
        = SetDuration String
    
    
    update : Msg -> Model -> Model
    update msg model =
      case msg of
        SetDuration s ->
          let result =
            String.toInt s
          in
            case result of
              Ok v ->
                { model | duration = v }
    
              Err message ->
                model
    
    
    -- VIEW
    
    
    view : Model -> Html Msg
    view model =
      div []
        [ select [ onInput SetDuration ]
                 (List.range 0 12 |> List.map intToOption)
        , div [] [ text <| "Selected: " ++ (toString model.duration) ]         
        ]
    
    
    intToOption : Int -> Html Msg
    intToOption v =
      option [ value (toString v) ] [ text (toString v) ]
    

    【讨论】:

    • 是否有理由不将其标记为答案?少了很多麻烦。
    • 不幸的是,目前不像onChange那样跨浏览器兼容。 caniuse.com/#search=oninput
    • 除了 Opera Mini 之外的所有东西?这很兼容。
    • onInput 在 Internet Explorer 中不会为 select 触发,因此兼容性比 @RobertFischer 建议的要有限。
    【解决方案2】:

    更新:onInput 有效,请参阅下面使用 0.19 工作代码的另一个答案:https://stackoverflow.com/a/41516493/540810

    是的,您需要使用on 来处理更改事件。如果您查看 Elm 中内置的 source for other event handlers,例如 onClick,您会发现它们都是使用 on 函数构建的。

    这是一个使用 elm-community/html-extra 中的 targetValueIntParse 将选项中的字符串值转换为 int 的示例。

    更新到 Elm-0.18

    import Html exposing (..)
    import Html.Events exposing (on)
    import Html.Attributes exposing (..)
    import Json.Decode as Json
    import String
    import Html.Events.Extra exposing (targetValueIntParse)
    
    
    main =
        beginnerProgram { model = { duration = 1 }, view = view, update = update }
    
    
    durationOption duration =
        option [ value (toString duration) ] [ text (toString duration) ]
    
    
    view : Model -> Html Msg
    view model =
        Html.div []
            [ h2 [] [ text "Month selector" ]
            , select [ on "change" (Json.map SetDuration targetValueIntParse) ]
                (List.map durationOption (List.range 1 12))
            , div [] [ text <| "Selected: " ++ (toString model.duration) ]
            ]
    
    
    type Msg
        = SetDuration Int
    
    
    type alias Model =
        { duration : Int }
    
    
    update msg model =
        case msg of
            SetDuration val ->
                { model | duration = val }
    

    你可以在浏览器https://runelm.io/c/ahz运行这个例子

    【讨论】:

    • 感谢您的回复。我需要更多的技能来理解这段代码中附加的内容。
    • 为什么标准库中不存在onChange
    • 不要忘记您可以在option 元素中使用Html.Attributes.selected = True 以确保所选选项始终正确显示在选择框中。
    【解决方案3】:

    这是 Elm 0.19 的更新:

    module Main exposing (main)
    
    import Browser
    import Html exposing (..)
    import Html.Events exposing (on)
    import Html.Attributes exposing (..)
    import Json.Decode as Json
    import String
    import Html.Events.Extra exposing (targetValueIntParse)
    
    
    main =
        Browser.sandbox { init = { duration = 1 }, view = view, update = update }
    
    
    durationOption duration =
        option [ value (String.fromInt duration) ] [ text (String.fromInt duration) ]
    
    
    view : Model -> Html Msg
    view model =
        Html.div []
            [ h2 [] [ text "Month selector" ]
            , select [ on "change" (Json.map SetDuration targetValueIntParse) ]
                (List.map durationOption (List.range 1 12))
            , div [] [ text <| "Selected: " ++ (String.fromInt model.duration) ]
            ]
    
    
    type Msg
        = SetDuration Int
    
    
    type alias Model =
        { duration : Int }
    
    
    update msg model =
        case msg of
            SetDuration val ->
                { model | duration = val }
    

    【讨论】:

      【解决方案4】:

      这适用于 Elm 0.19.0 上的 Elliehttps://ellie-app.com/58wGf2YsR9Ya1

      完整代码:

      import Browser
      import Html exposing (..)
      import Html.Events exposing (on)
      import Html.Attributes exposing (..)
      import Json.Decode as Json
      import String
      import Html.Events.Extra exposing (targetValueIntParse)
      
      main =
          Browser.sandbox { init = init, view = view, update = update }
      
      init =
          { duration = 1 }
      
      durationOption duration =
          option [ value (String.fromInt duration) ] [ text (String.fromInt duration) ]
      
      
      view : Model -> Html Msg
      view model =
          Html.div []
              [ h2 [] [ text "Month selector" ]
              , select [ on "change" (Json.map SetDuration targetValueIntParse) ]
                  (List.map durationOption (List.range 1 12))
              , div [] [ text <| "Selected: " ++ (String.fromInt model.duration) ]
              ]
      
      
      type Msg
          = SetDuration Int
      
      
      type alias Model =
          { duration : Int }
      
      
      update msg model =
          case msg of
              SetDuration val ->
                  { model | duration = val }
      

      【讨论】:

        【解决方案5】:

        onInput 处理程序的示例(您也可以查看Ellie):

        module Main exposing (main)
        
        import Browser import Html exposing (Html, button, div, text, select, option) import Html.Attributes exposing (value, selected) import Html.Events exposing (onInput) import Dict exposing (Dict)
        
        type alias Model =
            { options : Dict Int (String, Bool)
            }
        
        
        initialModel : Model initialModel =
            { options = Dict.fromList [(0, ("All time", False)), (1, ("One week", True)), (2, ("24h", False))] 
            }
        
        
        type Msg
            = Select String
        
        
        update : Msg -> Model -> Model update msg model =
            case msg of
                Select value ->
                    case String.toInt value of
                        Just selectedID ->
                            let
                                changeSelection id (label, _) =
                                    if id == selectedID then
                                        (label, True)
                                    else
                                        (label, False)
                            in
                            {model | options = Dict.map changeSelection model.options}
        
                        Nothing ->
                            model
        
        
        
        view : Model -> Html Msg view model =
            let
                toOption (id, (label, isSelected)) =
                    option [value (String.fromInt id), selected isSelected] [text label]
            in
            div []
                [ select [onInput Select] (List.map toOption <| Dict.toList model.options)
                , div [] [text "DEBUG"]
                , div [] [text <| Debug.toString model.options]
                ]
        
        
        main : Program () Model Msg main =
            Browser.sandbox
                { init = initialModel
                , view = view
                , update = update
                }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-01-22
          • 1970-01-01
          • 1970-01-01
          • 2020-11-10
          • 1970-01-01
          相关资源
          最近更新 更多