diff --git a/src/ngAnimate/animation.js b/src/ngAnimate/animation.js index 73747140fc52..581263b12338 100644 --- a/src/ngAnimate/animation.js +++ b/src/ngAnimate/animation.js @@ -106,7 +106,16 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) { result = result.concat(row); } - return result; + var terminalAnimations = []; + var parentAnimations = []; + forEach(result, function(result) { + if (result.terminal) { + terminalAnimations.push(result.fn); + } else { + parentAnimations.push(result.fn); + } + }); + return [parentAnimations, terminalAnimations]; } } @@ -220,11 +229,23 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) { var anim = sortAnimations(toBeSortedAnimations); var finalLevel = anim.length - 1; - forEach(anim, function(entry) { - if (!entry.terminal) { + // sortAnimations will return two lists of animations. The first list + // is all of the parent animations that are likely class-based and the + // second list is a collection of the rest. Before we run the second + // list we must ensure that atleast one reflow has been passed such that + // the preparation classes (ng-enter, class-add, etc...) have been applied + // to their associated element. + if (anim[0].length) { + forEach(anim[0], function(triggerAnimation) { $$forceReflow(); - } - entry.fn(); + triggerAnimation(); + }); + } else { + $$forceReflow(); + } + + forEach(anim[1], function(triggerAnimation) { + triggerAnimation(); }); }); diff --git a/test/ngAnimate/integrationSpec.js b/test/ngAnimate/integrationSpec.js index d448dc3b2d85..b56bb78c4866 100644 --- a/test/ngAnimate/integrationSpec.js +++ b/test/ngAnimate/integrationSpec.js @@ -306,7 +306,7 @@ describe('ngAnimate integration tests', function() { }); }); - it('should not issue any reflows for class-based animations if none of them have children with queued animations', function() { + it('should only issue one reflow for class-based animations if none of them have children with queued animations', function() { module('ngAnimateMock'); inject(function($animate, $compile, $rootScope, $rootElement, $$rAF, $document) { element = jqLite( @@ -328,11 +328,35 @@ describe('ngAnimate integration tests', function() { $rootScope.exp = true; $rootScope.$digest(); - expect($animate.reflows).toBe(0); + expect($animate.reflows).toBe(1); $rootScope.exp2 = true; $rootScope.$digest(); + expect($animate.reflows).toBe(2); + }); + }); + + it('should always issue atleast one reflow incase there are no parent class-based animations', function() { + module('ngAnimateMock'); + inject(function($animate, $compile, $rootScope, $rootElement, $$rAF, $document) { + element = jqLite( + '
' + + '{{ item }}' + + '
' + ); + + $rootElement.append(element); + jqLite($document[0].body).append($rootElement); + + $compile(element)($rootScope); + $rootScope.$digest(); expect($animate.reflows).toBe(0); + + $rootScope.exp = true; + $rootScope.items = [1,2,3,4,5,6,7,8,9,10]; + $rootScope.$digest(); + + expect($animate.reflows).toBe(1); }); }); });