I have a block with ng-repeat
that is defined like this:
<div ng-show="isPageSelected(item.page)" class="block" ng-repeat="item in data"> ... </div>
Currently I can switch between those blocks, by clicking certain elements. It works via ng-show="isPageSelected(item.page)"
as you might have guessed. It all works fine, but they are switching instantly and I want to add an animation, a simple fade in/fade out will do.
So, the block that is no longer selected should fade out and when it's gone a new block should fade in. When I'm using ngAnimate
they fade in and fade out simultaneously. I need the first block to disappear completely and be hidden with display: none;
and when it's done the next block should appear and fade in. It's a rather straightforward task when using jQuery, but how do I do that elegantly with Angular.js?
I have a strong suspicion that Angular.js isn't exactly a good choice for a site with complex animations.
EDIT: To simplify my question, all I need to do is
- On a button click start an animation;
- When an animation has been finished, change model;
- Run another animation.
Since I need to change the model after an animation, it's probably not possible to do it via pure CSS. The only way I know of triggering animations on specific elements in angular is to create a directive, pass a scope variable into the directive, create watcher for that variable in the directive and then change the variable from the controller:
<div animation="page"></div>
app.directive('animation', function(){ return { scope: { page: '=animation' }, link: function(scope, element){ scope.$watch('page', function(newVal){ ... }); } }; });
I guess it would work, but it seems really bloated to create a directive just for that. Also, how would I change $scope.page
with this approach only when the animation has been finished? Add another scope variable just to trigger an animation and somehow change $scope.page
when an animation has been finished? It's possible to do it with ngFx
module, but the amount of code it takes is just ridiculous. At this point I think adding jQuery animations to the controller would be a prettier way to solve it.
EDIT: That's how it looks like with jQuery animations:
$scope.changePage = function(page) { $('.block').animate({opacity: 0}, 500, function(){ $scope.page.id = page; $scope.$apply(); $(this).animate({opacity: 1}, 500); }); };
It works fine and it's not quite as verbose as the way with directives, but I have to use CSS selectors and that's just feels very "unangular". Do you guys use something similar when dealing with animations?
EDIT: Somewhat similar approach using ngFx
:
<div ng-hide="switchPageAnimation" class="block fx-fade-normal fx-speed-300 fx-trigger">
In the controller:
$scope.switchPageAnimation = false; $scope.changePage = function(page) { if($scope.page.id === page || $scope.switchPageAnimation) return; $scope.switchPageAnimation = true; $scope.$on('fade-normal:enter', function(){ $scope.page.id = page; $scope.switchPageAnimation = false; }); };
I'm not using CSS selectors, but still it looks awful. I have to define a scope variable for the animation and then check if the animation is already running. I feel like I am missing something really obvious.
1.3.8
. I'm also usingngFx
with version1.0.5
. Angular-animate has the same version as Angular, if I understand it correctly.