Route-linked page transitions in AngularJS

I am new to AngularJS and would like to implement route dependent page transitions. For example, I would like the page to slide left, shift right, or disappear depending on the route.

My “Plunker” below accomplishes this by listening to the $ routeChangeSuccess event, and then applying a CSS class with a special transition style to input and exit views (inspired by http://phillippuleo.com/articles/scalable-approach-page-transitions-angularjs ):

http://plnkr.co/edit/ee4CHfb8kZC1WxtDM9wr?p=preview

However, calling the $ scope method. $ apply () in the event listener will cause AngularJS to issue the error message '$ digest is already in progress'. But if I do not call $ scope. $ Apply (), the CSS class of the outgoing view is not updated, and the animation does not work correctly.

What's going on here?

+8
angularjs
source share
2 answers

I looked into your plunker. The problem is how you use classes to animate your views.

When the $routeChangeSuccess event is fired, ngView has already removed the class before you get the chance to change direction. You redefine it by applying the new class so quickly that it is not noticed, but then you get a digest error.

My solution ( plunker ):

I came up with a directive:

 app.directive('animClass',function($route){ return { link: function(scope, elm, attrs){ var enterClass = $route.current.animate; elm.addClass(enterClass); scope.$on('$destroy',function(){ elm.removeClass(enterClass); elm.addClass($route.current.animate); }) } } }); 

Declare animate parameter for each route:

 app.config(function($routeProvider) { $routeProvider. when("/page1", { templateUrl: "page1.html", controller: "Page1Ctrl", animate: "slideLeft" }). when("/page2", { templateUrl: "page2.html", controller: "Page2Ctrl", animate: "slideRight" }). otherwise({ redirectTo: "/page1" }); }); 

And just add it to ngView like this:

 <div ng-view ng-controller="ViewCtrl" anim-class class="view"></div> 

CSS:

 .view { width: 100%; padding-left: 1em; position:absolute; top: 0; left: 0; } .slideLeft.ng-enter, .slideLeft.ng-leave, .slideRight.ng-enter, .slideRight.ng-leave { -webkit-transition:all 1s; transition:all 1s; } .slideLeft.ng-enter { left:100%; } .slideLeft.ng-enter.ng-enter-active { left:0; } .slideLeft.ng-leave.ng-leave-active { left:-100%; } .slideRight.ng-enter { left:-100%; } .slideRight.ng-enter.ng-enter-active { left:0; } .slideRight.ng-leave.ng-leave-active { left:100%; } 
+23
source share

My current approach to this is to check if angular is already in the digest loop or not using this snippet:

 if (!($scope.$$phase)) $scope.$apply(); 

This is not very pretty, but, unfortunately, this is the only approach that I have found so far for the specific problem you are describing.

0
source share

All Articles