2

Essentially is there a simple way to leverage the ng-enter and ng-leave hooks on the ng-repeat directive to animate a basic slider left and right?

You can see the plunk here which is almost working.

I have a basic slider that transitions through a list of elements one page at a time using a partition filter and ng-repeat. This works as expected except when you switch directions, in which case the ng-leave transition on the previous direction is run causing a erroneous result.

I could write a custom slider directive or even use the angular-ui carousel but I don't want to over-complicate such a simple example if indeed a simple solution does exist. Any help would be much appreciated.

2 Answers 2

2

This screenshot shows the problem, and points to the solution.

angular-animate.js

The element passed to the animation leave function has the old class value.

Oddly, I have not been able to replicate this screenshot because the $scope mysteriously became unavailable. $rootScope is always available though. But it does seem you could do this without injecting $rootScope.

My solution is this:

Decorate the $animate.leave function like this:

.config(function($provide) { $provide.decorator("$animate", function ($delegate, $rootScope) { $delegate.originalLeave = $delegate.leave; $delegate.leave = function (element, doneCallback) { // THIS IS THE ADDITIONAL FUNCTIONALITY $(element).removeClass("right").removeClass("left").addClass($rootScope.direction); $delegate.originalLeave(element, doneCallback); }; return $delegate; }); }) 

Then place the direction variable on the $rootScope, which will of course need to be injected into the controller.

This solution requires jQuery, but it could be easily done without it.

Here is the working Plunker

Sign up to request clarification or add additional context in comments.

5 Comments

You are correct, the element passed to the leave function has the old direction value as it is that class (or direction) that is 'leaving' the element. The problem with that solution, however, is that modifying angular-animate, a core AngularJS module, could affect other leave animations in the app and also mean you could no longer update to new releases without making the same changes. I was hoping for a simple solution, maybe there isn't one.
We can decorate the $animate service as shown in the new answer. This is pretty normal practice, and will not break anything so long as we are sensible about how the decoration is implemented. Also, a little more work and I'm pretty sure we could do it without $rootScope or jQuery.
That's a clever way to do it, will start playing with this and see how we go. What seemed such a simple problem has not been easy to solve. If nothing simpler comes to light shortly I will mark as answer, it's a good solution, appreciate the help!
jQuery Lite implements addClass and removeClass so no need for jQuery as they are already available on the element object. To remove any reference to $rootScope might need a simple provider so direction is available in config phase. Is it really that 'bad' to use $rootScope in this situation? Cheers again.
Having an issue, by using a decorator in this way once a direction has been set it will trigger the animation on every element with an ng-enter hook (ng-repeat, ng-switch). Setting a $timeout in the decorator for the duration of the animation to unset $rootScope.direction works but seem very hacky and could cause issues when multiple animations are triggered in short succession. Any thoughts here?
0

Use ng-fx! Documentation and install instruction can be found here

Here is an example of how it can be used with ng-repeat :

<ul ng-controller="FoodController"> <li class='fx-fade-down fx-speed-800 fx-easing-bounce' ng-repeat="food in foods"> {{ food }} </li> </ul> 

This will use a fx-fade-down effect on the ng-repeated item, in 800 ms, with an 'easing' of bounce.

Additionally "Note that ng-repeat will not trigger animations upon page load, the collection you are iterating over must be empty at first then populated, you can achieve this with a simple timeout or some other async operation" :

angular.module('foodApp', ['ngAnimate', 'fx.animations']) .controller('FoodController', function($scope, $timeout){ $timeout(function(){ $scope.foods = ['apple', 'muffin', 'chips']; }, 100); }); 

1 Comment

From the documentation I don't see how ng-fx can solve this specific problem, it can apply an animation on enter and leave but I need different animations not based on a static class. Would it be possible to modify the Plunk to show what you mean? I was hoping to use only CSS animations and not have to include a GSAP library (I am aware of the advantages though) but happy to consider this if it can be applied, cheers.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.