问题描述
我有两个 div
html元素(具有 contenteditable
属性),我想获得de <$ c触发按键
时元素的$ c> id 属性(以及 onblur
事件)。
I have two div
html elements (with contenteditable
attribute) and I would like to get de id
attribute of the element when keypress
is triggered (onblur
event as well).
这是我当前的代码(它不起作用,我添加了任何注释):
This is my current code (it does not work, I have added any comments):
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
中的事件:
The following examples do not trigger the events in 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中可以使用:
However, in javascript it works: http://jsfiddle.net/MBags/
推荐答案
除非示例中没有其他明显的限制,您可以在 KeyPressed
并通过以下方式传递ID:
Unless there are additional constraints not evident from your example you could just add an extra argument to KeyPressed
and pass the id through that:
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
但是,您可能不应该依赖字符串首先是ids,因为字符串型数据很容易出错。理想情况下,每个组件都有单独的 Msg
变体:
However, you probably shouldn't rely on string ids in the first place, since stringly typed data is very error-prone. Ideally you'd have separate Msg
variants for each component:
type Msg
= Div1KeyPressed Int
| Div2KeyPressed Int
或者如果您需要更多动态性,可以使用自定义 ID
类型:
Or if you need a bit more dynamism you could use a custom Id
type:
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
这篇关于触发事件时获取ID属性(ELM v0.19.1)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!