【问题标题】:Getting ID attribute when event is triggered (elm v0.19.1)触发事件时获取 ID 属性(elm v0.19.1)
【发布时间】:2020-02-01 10:02:10
【问题描述】:

我有两个div html 元素(带有contenteditable 属性),我想在触发keypress 时获取元素的id 属性(onblur 事件也是如此)。

这是我当前的代码(它不起作用,我添加了任何 cmets):

module Mytest exposing (main)

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

type alias Model =
    { div1 : String
    , div2 : String
    }

initialModel : Model
initialModel =
    { div1 = "test1"
    , div2 = "test2"
    }

init : () -> ( Model, Cmd Msg )
init () =
    ( initialModel, Cmd.none )

view : Model -> Html Msg
view model =
    div []
        [ div [ id "div1", contenteditable True, onKeyPress KeyPressed ] [ text model.div1 ]
        , div [ id "div2", contenteditable True, onKeyPress KeyPressed ] [ text model.div2 ]
        ]

type Msg
    = KeyPressed Int

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        KeyPressed code ->
            let
                -- is there any way to use Debug.log without let block?
                a = Debug.log "div1 event" code
            in
                -- keypressed on div1 should be update div1 field model
                -- the same to div2
                ({model | div1 = String.fromInt code}, Cmd.none)

subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.none

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

onKeyPress : (Int -> msg) -> Attribute msg
onKeyPress tagger =
  on "keypress" (Json.map tagger keyCode)

编辑:

以下示例不会触发div contenteditable中的事件:

onInput : (String -> msg) -> Attribute msg
onInput tagger =
    on "input" (Json.map tagger keyCode)

onBlur : (String -> msg) -> Attribute msg
onBlur tagger =
    on "blur" (Json.map tagger targetValue)

onInput : (String -> msg) -> Attribute msg
onInput tagger =
    stopPropagationOn "DOMCharacterDataModified" <|
        Json.map alwaysStop (Json.map tagger (Debug.log "bbb" targetValue))

alwaysStop : a -> (a, Bool)
alwaysStop x =
    (x, True)

但是,在 javascript 中它可以工作:http://jsfiddle.net/MBags/

【问题讨论】:

    标签: events event-handling elm


    【解决方案1】:

    除非您的示例中没有明显的其他约束,否则您可以向 KeyPressed 添加一个额外的参数并通过它传递 id:

    type Msg
        = KeyPressed String Int
    
    view : Model -> Html Msg
    view model =
        div []
            [ div [ id "div1", contenteditable True, onKeyPress (KeyPressed "div1") ] [ text model.div1 ]
            , div [ id "div2", contenteditable True, onKeyPress (KeyPressed "div2") ] [ text model.div2 ]
            ]
    
    update : Msg -> Model -> ( Model, Cmd Msg )
    update msg model =
        case msg of
            KeyPressed id code ->
                -- Now you have the id
    

    但是,您可能首先不应该依赖字符串 ID,因为字符串类型的数据非常容易出错。理想情况下,每个组件都有单独的 Msg 变体:

    type Msg
        = Div1KeyPressed Int
        | Div2KeyPressed Int
    

    或者,如果您需要更多活力,您可以使用自定义 Id 类型:

    type Id
        = Div1
        | Div2
    
    type Msg
        = KeyPressed Id Int
    
    view : Model -> Html Msg
    view model =
        div []
            [ div [ contenteditable True, onKeyPress (KeyPressed Div1) ] [ text model.div1 ]
            , div [ contenteditable True, onKeyPress (KeyPressed Div2) ] [ text model.div2 ]
            ]
    
    update : Msg -> Model -> ( Model, Cmd Msg )
    update msg model =
        case msg of
            KeyPressed Div1 code ->
                -- update model.div1
    
            KeyPressed Div2 code ->
                -- update model.div2
    

    【讨论】:

    • 谢谢。我想如果没有更好的解决方案,我可以使用第一个解决方案
    • 你知道不使用let-in块是否可以使用Debug.log吗?
    • 您通常会使用它来代替您正在记录的值,因为它返回给定的值。例如。你可以在任何你使用code的地方使用(Debug.log "div1 event" code)
    • 您认为更好的解决方案是什么?
    • 我真的需要在写入时(按下键时)用 div(contenteditable)更新我的模型
    猜你喜欢
    • 2010-09-08
    • 2011-06-01
    • 1970-01-01
    • 2011-02-08
    • 2017-04-27
    • 2012-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多