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)
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:
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.
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 =
LowerEvent Value
| 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 -> ...
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
As far as worrying about the order in which events are executed, this is already the nature of async JavaScript and we should be coding in away that event ordering is either controlled through the reactive Elm Architecture and/or that code is written in a way that it shouldn’t matter
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.