Open runspired opened 9 years ago
+1 to this. I would be open to PRing the following implementation that I recently implemented on Ember 1.13, however I'm not privy to API changes that may or may not happen in liquid fire as a result of the new glimmer lifecycle hooks and Ember 2.0.
didAnimateIn
lifecycle hook for liquid fire
How this looks up the component in order to fire the event deserves more discussion, however this does work and is fairly simple. I would like to remove the requirement of declaring an attribute on the component, and this also introduces the requirement(?) for custom transitions to fire this hook.
@aortbals I've played around with a few implementations using the view registry and grabbing the view id from the element, seemed like a possible better approach.
@runspired Part of the reason I went down the route of an explicit attr on the component was that it seemed the least error prone. Checking for element
didn't work in all use cases I tried. I think we're in agreement though - there needs to be a supported way of getting access to the elements that are transitioning. This is hard to implement otherwise.
@aortbals I missed that you'd done that. It's only error prone if there's no element for the root view/component. I've been using a flag on tag-less components and views too. Apparently tag-less will stop being a thing though :)
I've also moved to function hooks instead of events.
Any status update on this? I'm having trouble focusing a form field after transitioning.
I agree we need a feature here, but I don't think lifecycle hooks on components are the right API.
A hook named didAnimate
probably shouldn't fire if there was no animation. But then you don't have a single reliable place to put behaviors that should always happen after animations have finished -- whether or not any animations are present.
A strawman idea:
{{#with-animation-detector as |d|}}
{{my-component shouldFocus=d.animationIsDone}}
{{/with-animation-detector}}
// my-component.js
didRender() {
if (this.get('shouldFocus')) {
this.$('.thing').focus();
}
}
If no animations are present, the animation detector will immediately yield { animationIsDone: true }
and the component will focus on the very first render. If an animation is running, it won't yield with that value until after it completes (which is also when we tend to trigger a render anyway to clear out the old states that have finished animating away).
👍 for this feature - my use case is a (non-liquid-fire) modal written with ember-elsewhere that shows up for an async promise then fades out after success. I want to be able to fire an action when the modal is done fading out.
@ef4 did any progress get made on this topic? what's the best path forward now in 2018?
Best path forward is somebody proposes an in-template API for this (either like the one I showed above, or as a helper instead, which I think would now be possible). It would go in ember-animated, not liquid-fire, because all component-level animation concerns are going to be handled in ember-animated (which needs to get integrated into liquid-fire soon).
Is there movement on this issue? I recently implemented a MutationObserver
to detect the presence of liquid-animating
on <div class="liquid-container"></div>
to solve this issue. Would love to have these hooks exposed for usage, especially for liquid-bind
{{#liquid-bind model
willAnimateTransition=(action "didAnimationStart")
didAnimateTransition=(action "didAnimationEnd")
as | currentModel |
}}
...
{{/liquid-bind}}
What I said above still applies. Putting hooks directly onto the animator components is not sufficient to write correct code. It's fragile. It doesn't account for animator nesting or interruption.
For example, if you have a component that needs to do something after it has finished getting animated (often something like focus), it's just not correct to stick an event on one particular liquid-bind. You need to notice if anybody all the way up your component hierarchy is animating. Because if later somebody adds a liquid-outlet far above you, your focusing will break.
We already have the implementation to support all this in ember-animated. It just needs somebody to put a pleasant public API around it. For example, the -ea-motion
service has methods like observeAnimations
, observeDescendantAnimations
, and observeAncestorAnimations
.
We could package those up as element modifiers, which would result in a really nice API:
<input {{finished-animating this.setFocus}}/>
We've had lot of great progress lately in both ember-animated and liquid-fire to bring them into alignment.
Views/Components animated by liquid-fire should have access to animation state hooks. The hooks need no guarantee of order beyond surrounding
didInsertElement
.I've implemented the latter of these hooks by wrapping my custom transitions (and
liquid-fire
's default transitions) in the following manner that only works with non tagless views/components (I had trouble finding a way to get the view/component more easily).The primary benefit of such a hook is being able to delay some events/actions/processing/rendering until after the animation has completed. In my case I use it like this to keep various components / async-components from rendering until the ideal time.
I also use it like this to prevent the keyboard on mobile from activating until after the transition completes:
I'd rather this not be implemented as an events but as
init
style method hooks which you can chain via_super
(thanks to @stefanpenner for pointing out the value of this to me)