angular-ui / ui-router

The de-facto solution to flexible routing with nested views in AngularJS
http://ui-router.github.io/
MIT License
13.54k stars 3k forks source link

Is there no means of customizing `ui-view` transition behavior? #305

Closed ghost closed 11 years ago

ghost commented 11 years ago

ui-view, like ng-view before it, assumes that content should blink in and out of existence abruptly, and as such they both support only enter and leave animations. When a state transition is detected, the old content is obliterated before the new content is rendered regardless of whether or not ng-animate is in play. The only real difference is the amount of time the code waits before performing the destruction operation.

This behavior precludes many popular and inherently more desirable transition options, such as cross fades, slides and wipes, where new view content and old view content need to co-exist for the duration of a transition, removing the old content only upon completion.

Looking at the code for $ViewDirective, I don't see any way to alter this behavior without replacing ui-view entirely, and I imagine that's going to confuse some other parts of the router since the existing implementation seems to be setting and consuming a bit of expando data. I can certainly roll a custom directive that registers its own $stateChangeSuccess handler, but I can't ensure that it is invoked before ui-views, nor can I prevent ui-views from running, as its event deregistration function is never assigned to anything.

Am I missing something or is this just the best Angular's $animator service can do?

nateabele commented 11 years ago

Are you on master or the last release? We use slide animations in most of our transitions with no issues.

ghost commented 11 years ago

Release. Looking at master, I don't see anything different. The old content is destroyed before the new content is rendered: https://github.com/angular-ui/ui-router/blob/master/src/viewDirective.js#L37

Do you have an example? I can certainly perform slides now, but one view has to slide out before the other slides in.

timkindberg commented 11 years ago

Can't confirm right now (on my phone) but I thought for sure our FAQ example did this. https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-animate-ui-view-with-ng-animate

ghost commented 11 years ago

Setting DOM breakpoints on subtree modifications, that example does indeed result in two h1 elements cohabitating within the .well div:

Screenshot

This is a situation which absolutely never occurs in my case, and the primary differences I notice are that my view/states are nested, object-based, and the templates render a lot of data which is provided by a promise in the state's resolve map.

nateabele commented 11 years ago

Mine is a client app, but I can try and extract a working example. My main animated transitions are between sibling states that are the children of one container state, all of which load data over the network through resolves. Not sure what else to tell you.

nateabele commented 11 years ago

@oncomeme Also:

The old content is destroyed before the new content is rendered

...is not even a remotely accurate understanding of how that code operates.

Also, pro tip: when asking for volunteer help from people on a pre-alpha Open Source project, I can pretty much guarantee you'll get further with fewer assumptions and less begging the question.

ghost commented 11 years ago

You'll have to forgive me if I am not as knowledgable as to the inner workings of this project as someone who was responsible for producing it (or developing pathological delusions of adequacy while merging a couple of pull requests as the case may sometimes be in the wacky open source street cred world), but this is an accurate description of what that code is currently doing right in front of my eyes.

The root problem I'm hitting up against appears to be in the timing of Angular's attempts at divining the appropriate transition durations to feed to setTimeout, which in my stylesheet are not constant as the classes cycle through. Both this and my disappointment regarding the immutability of directives once registered and established remain significant problems, but they do seem to be problems with Angular itself (as well as the relative un-reliability of transitionEnd events on the part of the browser vendors) rather than this particular project. While I'd still like to know whether or not there is any idiomatic way to augment existing directives, you are correct that this is probably not the greatest place in the world to ask that particular question as it's unlikely anyone would know the answer.

Also, pro tip: If you don't want people using and asking questions about your software, you can hide the issue tracker with a single click anytime. I can pretty much guarantee your cliché, misdirected nerd rage and ability to spew ridiculous Ron Paul quotes entitles you to no special exemption from the constant need for improvement in all facets of life.

jeme commented 11 years ago

@oncomeme here is a short example that shows that both the entering and leaving element are in the "stage" at the same time in a "wave" animation.

http://jsfiddle.net/fEbgM/25/

But this can be hard to observe unless it's slow and you add those borders.

Also when we speed things up we need to keep the timing in mind, angular is just trying to make things really easy and convenient for us, in a "this is how it should really work" way, but the thing is, ones you dive into CSS animations there isn't any hooks (Not that I know of, not yet at least) to give you information about the process of the animation... So you end up having a timeline in CSS and another in JS, and keeping those in 100% sync is impossible, but at least angular gets really close most of the time.

This is also observable in the example I linked where the "views" sometimes overlap just slightly. Meaning that entering the new element was started before leaving the old one.

If you wan't to be more sure about your timing of the animations you will have to revert back to JavaScript (e.g. jQuery has some nice hooks for it) based animations. This is also possible to do with Angular, and they sort of made it easy...

Here are some great articles on animations (if you haven't already seen those):