Получение атрибута ID при запуске события (elm v0.19.1) - PullRequest
2 голосов
/ 01 февраля 2020

У меня есть два div html элемента (с атрибутом contenteditable), и я хотел бы получить атрибут id элемента, когда срабатывает keypress (также событие onblur).

Это мой текущий код (он не работает, я добавил комментарии):

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/

1 Ответ

3 голосов
/ 01 февраля 2020

Если из вашего примера не видно дополнительных ограничений, вы можете просто добавить дополнительный аргумент к KeyPressed и передать через него идентификатор:

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

Однако вы, вероятно, не должны полагаться на строку идентификаторы в первую очередь, поскольку данные со строгой типизацией очень подвержены ошибкам. В идеале вы должны иметь отдельные 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
...