4

I wrote a simple program based on time example, to test what data are in events. It decodes JSON to value then encodes it back to JSON, then show it in SVG text element. And the only thing I get is {"isTrusted":true}.

Why that happens? How do I get another data of event? I'm using Firefox 49 and online compiler:

import Html exposing (Html)
import Svg exposing (..)
import Svg.Attributes exposing (..)
import Svg.Events exposing(on)
import Json.Decode as Json
import Json.Encode exposing (encode)

main =
  Html.program
    { init = init
    , view = view
    , update = update
    , subscriptions = subscriptions
    }

-- MODEL
type alias Model = String

init : (Model, Cmd Msg)
init =
  ("No event", Cmd.none)


-- UPDATE
type Msg
  = Event String

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    Event event ->
      (event, Cmd.none)


subscriptions model = Sub.none


stringifyEvent: Json.Encode.Value -> Msg
stringifyEvent x = 
  Event (encode 2 x)

-- VIEW

view : Model -> Svg Msg
view model =
    svg [ viewBox "0 0 300 300", width "300px", on "mousedown" (Json.map stringifyEvent Json.value) ] [ 
       text_ [x "0", y "30"] [text model]
    ]

When I try in console

svgElement.addEventListener('click', function(e) {console.log(e)})

It works with all the attributes.

Bunyk
  • 7,635
  • 8
  • 47
  • 79

2 Answers2

3

I do not know a way to achieve your goal. But I can give you an answer why it does the way you described.

If you look at the source code, you'll find that Elm runtime uses JSON.stringify() for converting Value to String.

And guess what... svgElement.addEventListener('click', function(e) {console.log(JSON.stringify(e))}) will give you {"isTrusted":true} when you click...

Tosh
  • 35,955
  • 11
  • 65
  • 55
0

As explained by @Tosh, the data is not correctly passed through for some events (e.g. also for CustomEvent).

However, there is an easy workaround by simply (mis)using only predefined events, for which it works correctly. A full list is available here.

One that's especially suited ist the MessageEvent. It has a data field for holding arbitrary data related to the message.

For your example, where the event type is pre-determined by the HTML element, you could wrap your HTML with a custom web-component, capture the emitted event, and re-emit the event as a MessageEvent.

this.dispatchEvent(
  new MessageEvent(
    "customData",
    {
      data: {"x": 123},
      composed: true,
    }
  )
)
onCustomData : Attribute Msg
onCustomData toMsg =
    on "customData"
        (JD.field "data" (JD.field "x" JD.int)
            |> JD.map XValueReceived
        )
adius
  • 13,685
  • 7
  • 45
  • 46