Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use of ng-animate in ui-view. #85

Closed
jeme opened this issue Apr 15, 2013 · 19 comments
Closed

Use of ng-animate in ui-view. #85

jeme opened this issue Apr 15, 2013 · 19 comments

Comments

@jeme
Copy link
Contributor

jeme commented Apr 15, 2013

Hi @ksperling

Just had a look at what you did in in ui-view for ng-animate... in regards to #22...

In my experience, we might wan't to add a distinction between the view being loaded as part of a compile/render or as an state update.

The reason for this is that the different parts of the view seems to end up sliding (using wave ) independently which looks really awkward, at least I experienced that in my own sample at my own routing solution, so what I did was to add a flag to the update, where if the update wasn't called as part of state change, then I would load the view regularly...

You can have a peek if you like:
https://github.com/dotJEM/angular-routing/blob/master/src/directives/uiView.ts

I will see if I can't get the time to create a sample showing if the issue is present here or not later today, but I am at work now so can't use the time for it here.

This is just a hunch...

I am also considering adding some extra options to the view to leverage some of the issues with ng-animate paired with a view.

@jeme
Copy link
Contributor Author

jeme commented Apr 16, 2013

I am attempting to move my sample into the ui-router under samples (substates folder) on the branch https://github.com/angular-ui/ui-router/tree/issue-85 however I haven't quite gotten the example to fully work yet, but it is already clear that it exhibits "out of sync" sliding as i mentioned.

So it may be enough to discuss the issue, I expect that when that is done, the branch can just die again as it is a bit contaminated due to the structure at my own project, it was easier to copy it over like that.

@ksperling
Copy link
Contributor

@jeme sounds like a good idea. This means that if a bunch of nested views are displayed by a single state transition, only the outermost one would be animated?

I was also thinking that I'd like to be able to control the animation directly via something like $state.transitionTo('foo', {}, { animate: 'slide' }) (even though this may not make that much sense if more than one view is involved and you don't want to animate all of them)

@jeme
Copy link
Contributor Author

jeme commented Apr 16, 2013

Thats the idea yes, as I think that would be the most desired effect. I have found that as is, animations for views become really cumbersome in many cases (properly depending the chosen animation) so whatever help that can be offered from the ui-view would properly be helpfull... Like what I have to do atm is:

app.animation('wave-enter', function ($rootScope, $timeout) {
    return {
        setup: function (element) {
            var elm = $(element);
            var parent = elm.parent();
            elm.addClass('wave-enter-setup');
            parent.css({ 'height': elm.height() });
            parent.addClass('stage');

            return $rootScope.$watch(function () {
                parent.css({ 'height': elm.height() });
            });

        },
        start: function (element, done, memo) {
            var elm = $(element);
            var parent = elm.parent();
            elm.addClass('wave-enter-start');

            $timeout(function () {
                memo();

                elm.removeClass('wave-enter-setup');
                elm.removeClass('wave-enter-start');

                parent.removeClass('stage');
                parent.css('height', null);

                done();
            }, 2000);
        }
    };
});

app.animation('wave-leave', function ($rootScope, $timeout) {
    return {
        setup: function (element) {

            $(element).addClass('wave-leave-setup');
        },
        start: function (element, done, memo) {
            $(element).addClass('wave-leave-start');
            $timeout(function () {
                $(element).removeClass('wave-leave-setup');
                $(element).removeClass('wave-leave-start');
                done();
            }, 2000);
        }
    };
});

Which is just bud-ugly (and there is still a number of bugs to figure out in there)... but much of it is necessary as views properly aren't static, so in order to make sure the container maintains the views size as it enters the stage one has to keep updating that.

It might be helpful to let the view have an option to maintain it's height that way during animation, I am just not 100% on what the best approach on that is.

That brings me to a completely different scenario, some might wan't a "progress indicator" as a intermediate view until all view data is loaded, and then slide in the view... But this requires some more fundamental changes to the animation API from the core I think. (It might be solvable as is, but I haven't really seen how one would go by and do that).

As for the other idea about passing specific animations into transitions, I think that is still doable, because for views that gets loaded as part of compile, you would still just ignore it. As that part really comes down to where your calling update from...

Like so:

scope.$on('$stateChangeSuccess', function() { updateView(true); } );
updateView(false);

function updateView(doAnimate) { ... }

And then just alternate on do animate.

Edit: think I misunderstood a little, but yes I can that you don't wan't e.g. the "hint@" view to slide in as an example. So maybe we should just keep that out from now, I expect this is to leverage some of the "navigate up or down" kind of scenario?... or?

@ksperling
Copy link
Contributor

Yes, its pretty messy. The support for pure css animations makes it sound like its simple to do your own animation, but even just handling height and positioning of the old and new content make that pretty hard or impossible with just css.

I was also somewhat surprised that $animator doesnt have a native 'replace' method instead of relying on two independent enter and leave animations to run at the same time -- for some types of transitions having explicit access to both would probably make things like interpolating the height between the old and new content a lot easier.

@numair
Copy link

numair commented Apr 21, 2013

Sorry if this is a hijack of the thread -- is there any way to implement a "loading..." / progress-indicator middle-state right now? I am thinking it could be possible as its own state that then programmatically calls the next state? This doesn't offer an opportunity for animations that blend the two states, which I am guessing from the above comments is not-so-possible for a while...

@jeme
Copy link
Contributor Author

jeme commented Apr 21, 2013

@numair well, you could properly achieve something close in a more traditional angular way, where you define a view with 2 blocks... 1 is the loader and the other is the actual view, then simply using ng-show/ng-hide to switch from one to the other as the data gets loaded...

@ksperling
Copy link
Contributor

Maybe ui-view could listen for $stateChangeStart (in addition to
$stateChangeSuccess) to somehow add a loading indicator of some kind. You'd
have to not discard the existing DOM contents at that point though, as you
need to put it back in case the transition fails or is superseded by a
later transition.

Maybe $animator could have additional methods like $animator.busy(element,
onOrOff) which could then trigger the loading animation to start or stop.
ui-view would call $animator.busy(e, true) on $stateChangeStart if the
state change is going to affect the view, and $animator.busy(e, false) when
the transition fails or succeeds.

For animations that blend two states we would need a composite
$animator.replace() method in addition to the separate $animator.enter and
$animator.leave that exist currently.

On Sun, Apr 21, 2013 at 2:43 AM, Jens Melgaard notifications@github.comwrote:

@numair https://github.com/numair well, you could properly achieve
something close in a more traditional angular way, where you define a view
with 2 blocks... 1 is the loader and the other is the actual view, then
simply using ng-show/ng-hide to switch from one to the other as the data
gets loaded...


Reply to this email directly or view it on GitHubhttps://github.com//issues/85#issuecomment-16713943
.

@jeme
Copy link
Contributor Author

jeme commented Apr 22, 2013

Regarding the original issue, i committed the CS b627e0c if you would like to inspect that briefly.

ksperling added a commit that referenced this issue Apr 24, 2013
Still need to guard against $animator not being defined. Also avoid
having two variables 'doAnimate' in scope to make the code clearer.
@ksperling
Copy link
Contributor

@jeme thanks, looks good

@morgs32
Copy link

morgs32 commented Jul 3, 2013

@jeme, I think you're addressing my issue above, but I am still experiencing problems. ng-if does not seem to call "leave" animation? Here's a jsfiddle in case you have time to bother: http://jsfiddle.net/morgs32/xPxkX/1

@jeme
Copy link
Contributor Author

jeme commented Jul 3, 2013

@morgs32 Not really, not sure why this is, but if debug your example you will notice it doesn't recognize "animate" as a method on element (your using the angular jqlite implementation, apparently it doesn't include animate?).

In my example here: https://github.com/dotJEM/angular-routing/blob/master/samples/substates/index.html I use full jQuery, but even then I actually doesn't use animate... but that is another thing... never mind that...

Your properly thinking that "but the slide in works, so how can that work when animate doesn't work?"... That is actually due to your leave, the CSS in there combined with your "js-wave-base" ends up creating that effect just as you set the CSS left attribute to 0, the CSS animation is still applied. So actually your JS animation doesn't work at all... Not enter, not Exit...

Add full jQuery and it will start working... (oh and there is a typo in your first ng-animate def, there is a superfluous
'}' at the end)...

Like so: http://jsfiddle.net/xPxkX/17/

I have added a Comment in the Leave setup, as your call to "element.css" in this case is actually not really needed. Also you should properly remove your js-wave-base class from that element so it is pure js animation. Although the CSS animation part of it causes for a more smooth transition... And more oddly enough, without it it seems the animation alternates for every second pass o.O, maybe that's just my browser...

@morgs32
Copy link

morgs32 commented Jul 3, 2013

@jeme Thanks a ton that was incredibly helpful. Now on to figuring out how to animate the ui-view. Again - much appreciated.

@davidpfahler
Copy link
Contributor

What is the status? Is ng-animate working on ui-view directive? How can I help to make it happens?

@timkindberg
Copy link
Contributor

I thought this was working... have you tried it yet? Are you having problems? Might not hurt if I added an example to the FAQ.

@nateabele
Copy link
Contributor

Yup, it's working. Using it in an app right now. :-)

@timkindberg
Copy link
Contributor

@mlim1972
Copy link

With the latest update 0.2.0, the sample in jsfiddle broke. I've updated in this jsfiddle to fix it:
http://jsfiddle.net/mlim1972/fEbgM/46/

@nateabele
Copy link
Contributor

@mlim1972 Thanks! @timkindberg Can you update our sample fiddle when you get a chance?

@timkindberg
Copy link
Contributor

Fixed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants