I am considering fleshing out a proposal to expand the Html.Events.Options type to handle writing to the event object.
The context that triggered this proposal was my attempt to use the native HTML 5 Drag and Drop APIs in a simple project as an exercise in learning. The minimum implementation required I set data for the drag operation on the event.dataTransfer container due to a feature (bug?) in FireFox. ( See https://caniuse.com/#search=Drag )
I had looked through the available Elm packages that supported DnD to various degrees and concluded that they took one of two approaches:
- Ignore native DnD and simulate with Mouse events (which can only provide an incomplete solution)
- Leverage a soon-to-be-closed “back door” and use Html.Attributes.attribute to set custom event handlers to modify event.dataTransfer. ( See https://github.com/elm/virtual-dom/commit/56b5faa19fad198eb23e3c5f121c89b5dcbe7f3a )
In the short term, I went with #2. However, for a long-term, full-featured implementation of native DnD, neither of these will work. There is probably some way to leverage ports to make this happen, but that comes with its own disadvantages:
- Not supported on package.elm-lang.org
- Bypasses the Event architecture already established in Elm
- Higher complexity
I was thinking there might be a simple, generic, solution to this by opening up the Html.Events.Options type (which already allows us to modify the behavior of the event handler) to allow safely writing to the event object when the handler is executed. I haven’t done much research yet, but I’m guessing there are more native APIs that would benefit from this feature other than DnD.
Before I spent more time on this proposal, I wanted to throw this idea out to the community for your thoughts.
It looks like Firefox’s behavior is a bug, rather than a feature: https://bugzilla.mozilla.org/show_bug.cgi?id=1352852
There are other examples of needing to set data on dataTransfer:
Should this be a native package specific to the needs of drag and drop? That is, developed under elm-explorations, rather than proposing to open up writing to the event object generally?
The reason I ask is because writing to the events object sounds like it could lead to ‘spooky action at a distance’; a place for strange side-effects to lurk.
Can you provide a concrete example where writing to the event object would do that?
In my mind, its just data, not behavior. Any behavior that occurs because of pushing data on the event object would either be documented as API behavior or explicit to the code you are running (either on the JS side or Elm side).
I don’t have a concrete example, as I don’t have an API that lets me do that… only a hypothetical example.
Suppose an event propagates up, and at different levels of the DOM there are event handlers attached. The updated value of the event object will be given to the higher level handler - you could even put application state in there that exists outside of the Model.
Also, does Elm make any guarantees about the order in which events are processed? Lower first, then Higher? or can it sometimes be different?
What about the side effect to make the change to the event object, that needs to be processed in between Lower and Higher?
type Msg =
| HigherEvent Value
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
case msg of
LowerEvent val -> (model, Html.Event.updateEventObj ...) -- Info passed from here to line below, outside of the Model.
| HigherEvent val -> ...
Thanks for these points. Here are my thoughts:
- Regarding event handlers in higher level DOM elements receiving the Elm-updated event
- In an SPA, this would be explicitly known by the developer - no surprises there to deal with
- With an embeded Elm-app, this is outside the realm-of-concern for the Elm app and the engineer responsible for embedding the Elm-app would need to respond to this behavior, as appropriate. Hopefully the Elm engineer does a good job documenting this.
- We can already put state outside of the Elm Model via Ports, so this would not be new behavior
- Additionally, any of the state within the Event container will be easily accessible within Elm via JSON Decoders, so one could argue this might be the best place to put transient, external data
- I’m not sure I understand your example using LowerEvent/HigherEvent. I am only proposing we update the event container via explicit “on” event handlers which return “Attribute msg” types (not “Cmd msg” types). Second, we already commonly pass data around outside the model, for example, with “data-*” attributes on DOM elements, or accessing the myriad of other data available on the event object. I do not think my proposal creates any new methods of passing data.
Thanks for bringing up these concerns, they have really helped me think through this.
This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.