Can I do something like this?
fn handle_mouse_up(e: &web_sys::MouseEvent) -> MsgGenerator {
// ... do something with web_sys
yield Msg::Something;
// ... do something else with web_sys
yield Msg::SomethingElse;
}
Or
fn handle_mouse_up(e: &web_sys::MouseEvent) -> Vec<dyn Fn() -> Msg> {
vec![
|_| {
// actual render
// ... do something with web_sys
Msg::Something
},
|_| {
// next render
// ... do something else with web_sys
Msg::SomethingElse
}
]
}
I know rust's generator API is unstable. But is there a way to achieve this need?
I'd start by questioning why you want to do this in the first place. My guess is it's because you treat Msgs like functions. This is considered an anti-pattern in Elm. Partly because it leads to issues like this, but mostly because it makes it difficult to debug and evolve code where the logic is very entangled and messages depend on each other in complex ways. In many way this recreates the problems of the imperative model that the Elm architecture tries to solve.
In Elm there are, as far as I know, two "schools of thought" for naming Msgs: event-based and intent-based naming.
Event-based naming is what I consider the "proper" approach. Examples being CloseButtonClicked and GotSutffFromServer. It is a very simple and straight-forward convention to follow, meaning you never have to think much about naming, and it's very descriptive and easy to understand. It can also get rather verbose however.
Intent-based naming is the compromise approach, sacrificing some of the descriptiveness and clarity of event-based naming for terseness. With names like CloseDialog and LikePost it may at first glance look like function-based naming, but the difference is that Msgs should describe user intent, not developer intent.
For the purpose of code reuse, which I suspect is the underlying motivation here, I'd recommend just using functions called from handling each Msg in update. Code reuse is what functions are essentially for after all.
Thanks @glennsl .
I want this because the event handling requires multiple rerenders.
The problem what I want to solve, is a drag and drop where i need to catch the element I drop on.
For this I need to reset the dragging element's position first, which requires a rerender, then I need to check which element is on the actual mouse position.
Currently I'm using a workaround where I hide the element and unhide it after I get the element.
For this I need to reset the dragging element's position first, which requires a rerender, then I need to check which element is on the actual mouse position.
It sounds a bit cumbersome - can you use something like https://developer.mozilla.org/en-US/docs/Web/API/Document/drop_event instead?
Currently I'm using a workaround where I hide the element and unhide it after I get the element.
According to https://developer.mozilla.org/en-US/docs/Web/API/Document/elementFromPoint, you can toggle pointer-events instead of visibility (it sounds less invasive imho)
It sounds a bit cumbersome - can you use something like https://developer.mozilla.org/en-US/docs/Web/API/Document/drop_event instead?
I want this for SVG, which does not support drag* events.
According to https://developer.mozilla.org/en-US/docs/Web/API/Document/elementFromPoint, you can toggle pointer-events instead of visibility (it sounds less invasive imho)
Thanks for the advice.
Closing this because this is more likely the SVG's fault.
I'm still not sure how parallel message dispatching would help with this, as it still sounds to me like a sequence of messages should do the trick. But perhaps using Orders::after_next_render would be helpful.
I don't want to pollute update function with web_sys and view does not have Orders. But yes, after_next_render would solve the issue.
Yeah, I can see that. Another option for dealing with messy DOM interaction is to create a web component. That carries a big overhead in itself, of course, but at least it's encapsulated and can expose a nice, clean and declarative API.
Most helpful comment
I'd start by questioning why you want to do this in the first place. My guess is it's because you treat
Msgs like functions. This is considered an anti-pattern in Elm. Partly because it leads to issues like this, but mostly because it makes it difficult to debug and evolve code where the logic is very entangled and messages depend on each other in complex ways. In many way this recreates the problems of the imperative model that the Elm architecture tries to solve.In Elm there are, as far as I know, two "schools of thought" for naming
Msgs: event-based and intent-based naming.Event-based naming is what I consider the "proper" approach. Examples being
CloseButtonClickedandGotSutffFromServer. It is a very simple and straight-forward convention to follow, meaning you never have to think much about naming, and it's very descriptive and easy to understand. It can also get rather verbose however.Intent-based naming is the compromise approach, sacrificing some of the descriptiveness and clarity of event-based naming for terseness. With names like
CloseDialogandLikePostit may at first glance look like function-based naming, but the difference is thatMsgs should describe user intent, not developer intent.For the purpose of code reuse, which I suspect is the underlying motivation here, I'd recommend just using functions called from handling each
Msginupdate. Code reuse is what functions are essentially for after all.