Animating a newly-created component instance via CSS requires a call to requestAnimationFrame (or setTimeout) so that the newly applied style doesn't immediately overwrite the initial style. This is such a common UX scenario that it deserves consideration to be handled in core.
I suggest we add a new hook, ondomready perhaps, which fires on the next rAF tick.
I'm fairly certain this would only change 2 lines in coreRenderer (adding checks for ondomready in isLifecycleMethod and hasIntegrationMethods), and would add another condition to initLifecycle:
```
if (typeof source.ondomready === "function") hooks.push(function(){
requestAnimationFrame(function(){ source.ondomready.call(vnode.state, vnode) })
})
Just as a note: the implementation would likely be a little more complex, because it would need to do the following:
m.redraw()'s batching. requestAnimationFrame isn't available in all of Mithril's supported environments (notably IE9), and we should try to minimize how many callbacks we schedule.ondomready list rather than the standard hooks list. We can shortcut the hooks list because the callback is run when the animation frame is launched, not during synchronous rendering.this took many iterations for me to get right in domvm.
the key insight is that you need to fire these post-insertion hooks after forcing a reflow rather than assuming that requestAnimationFrame or setTimeout or Promise.resolve().then() covers the needed delay. you can force a reflow by simply accessing some expensive property like offsetHeight [1]. This was the only reliable method i found for getting this behavior to work properly.
[1] https://github.com/leeoniya/domvm/blob/2.x-dev/src/view/utils.js#L16
@leeoniya Thanks for the insight! 馃槃
@isiahmeadows sounds good! I'll investigate further and PR if there's a decent chance this will get accepted. Wearing your Collaborator hat, does this seem to you to be a good candidate for core? _(My gut says no, but I had to try...)_
@CreaturesInUnitards
Wearing your Collaborator hat, does this seem to you to be a good candidate for core?
I'm personally -0.5 on this, because this is the first time someone has requested something like this, and Mithril has even been used to power simple 2D games in the past. But if enough demand surfaces, I'm okay with the addition.
(We tend to be conservative when adding new features, because we like to keep the core as small as we practically can. Less to load, less to learn, less to remember.)
I hear you. I'll wait to see if others jump on either side before I do anything else. Thanks.
@pygy and @tivac Thoughts? (Note that I'm weakly for this being a third-party module rather than in core.)
I'm :-1: on this in core, but it seems like a very useful utility component so I'd like to see it implemented.
Are reflows global, or per element?
Couldn't we access root.offsetHeight before running the post-view hooks (no idea if it would be useful, would kill perf, etc...)?
@pygy I can't answer either question, but I think they would both be worthy of investigation.
@tivac This will be the last I'll push for this, but for the sake of argument:
I understand the Prime Directive to keep the API surface minimal, but it's not like adding this hook would be opening the floodgates to a thousand more proposed hooks. It could be reasonably argued that the lack of this hook is a blind spot.
The docs explicitly state that oncreate is useful for starting animations, so it comes as a surprise that vnode.dom isn't ready to be re-styled to that end. Whatever is decided about ondomready, the oncreate doc needs tweaking.
I'd be curious to know how the decision was made to include onbeforeupdate, which is so reviled by its author(s?) that the docs tell us to use it only as a last resort, and that needing to do so is probably an indicator of poor design. I would guess that the vast majority of mithril apps never need to use onbeforeupdate, and that a fairly high percentage would happily use ondomready if it was available.
All that being said, I can easily see how this might feel like feature creep, but I think if you polled the community you'd find a lot of votes for inclusion. I myself could legitimately replace every usage of oncreate with ondomready and suffer no perceivable penalty.
@CreaturesInUnitards The major difference for me is that ondomready is something you can do in user-land, onbeforeupdate requires framework support.
I think something like this as a component factory or wrapping component is pretty achievable, and where possible new functionality should be prototyped in user-land before landing in core.
@tivac gotcha, thanks for considering. I'll close.
Most helpful comment
this took many iterations for me to get right in domvm.
the key insight is that you need to fire these post-insertion hooks after forcing a reflow rather than assuming that
requestAnimationFrameorsetTimeoutorPromise.resolve().then()covers the needed delay. you can force a reflow by simply accessing some expensive property likeoffsetHeight[1]. This was the only reliable method i found for getting this behavior to work properly.[1] https://github.com/leeoniya/domvm/blob/2.x-dev/src/view/utils.js#L16