Skip to content

Commit 37af64a

Browse files
committed
fix(ngAnimate): correctly animate transcluded clones with templateUrl
Previously, `$animate` would decide whether an animation should be cancelled based on some assumption that didn't hold in specific cases (e.g. when animating transcluded clones with `templateUrl` directives on them for the first time). As a result, the entering elements would not be animated. This affected commonly used, structural built-in directives (`ngIf`, `ngRepeat`, `ngSwitch` etc). This commit fixes it by avoiding invalid assumptions (i.e. by taking into account the transformations that take place while compiling such elements). Fixes angular#15510
1 parent 288351b commit 37af64a

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

src/ngAnimate/animateQueue.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -302,13 +302,13 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
302302

303303
return $animate;
304304

305-
function queueAnimation(element, event, initialOptions) {
305+
function queueAnimation(originalElement, event, initialOptions) {
306306
// we always make a copy of the options since
307307
// there should never be any side effects on
308308
// the input data when running `$animateCss`.
309309
var options = copy(initialOptions);
310310

311-
element = stripCommentsFromElement(element);
311+
var element = stripCommentsFromElement(originalElement);
312312
var node = getDomNode(element);
313313
var parentNode = node && node.parentNode;
314314

@@ -479,6 +479,15 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
479479
markElementAnimationState(node, PRE_DIGEST_STATE, newAnimation);
480480

481481
$rootScope.$$postDigest(function() {
482+
// It is possible that the DOM nodes inside `originalElement` have been replaced. This can
483+
// happen if the animated element is a transcluded clone and also has a `templateUrl`
484+
// directive on it. Therefore, we must recreate `element` in order to interact with the
485+
// actual DOM nodes.
486+
// Note: We still need to use the old `node` for certain things, such as looking up in
487+
// HashMaps where it was used as the key.
488+
489+
element = stripCommentsFromElement(originalElement);
490+
482491
var animationDetails = activeAnimationsLookup.get(node);
483492
var animationCancelled = !animationDetails;
484493
animationDetails = animationDetails || {};

test/ngAnimate/animateSpec.js

+20-2
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,26 @@ describe('animations', function() {
459459
expect(commentNode[0].parentNode).not.toBe(parentNode);
460460
}));
461461

462+
it('enter() should animate a transcluded clone with `templateUrl`', function() {
463+
module(function($compileProvider) {
464+
$compileProvider.directive('foo', valueFn({templateUrl: 'foo.html'}));
465+
});
466+
467+
inject(function($animate, $compile, $rootScope, $templateCache) {
468+
parent.append(jqLite('<foo ng-if="showFoo"></foo>'));
469+
$templateCache.put('foo.html', '<div>FOO</div>');
470+
$compile(parent)($rootScope);
471+
472+
expect(capturedAnimation).toBe(null);
473+
474+
$rootScope.$apply('showFoo = true');
475+
476+
expect(parent.text()).toBe('parentFOO');
477+
expect(capturedAnimation[0].html()).toBe('<div>FOO</div>');
478+
expect(capturedAnimation[1]).toBe('enter');
479+
});
480+
});
481+
462482
it('enter() should issue an enter animation and fire the DOM operation right away before the animation kicks off', inject(function($animate, $rootScope) {
463483
expect(parent.children().length).toBe(0);
464484

@@ -2437,15 +2457,13 @@ describe('animations', function() {
24372457

24382458
return function($rootElement, $q, $animate, $$AnimateRunner, $document) {
24392459
defaultFakeAnimationRunner = new $$AnimateRunner();
2440-
$animate.enabled(true);
24412460

24422461
element = jqLite('<div class="element">element</div>');
24432462
parent = jqLite('<div class="parent1">parent</div>');
24442463
parent2 = jqLite('<div class="parent2">parent</div>');
24452464

24462465
$rootElement.append(parent);
24472466
$rootElement.append(parent2);
2448-
jqLite($document[0].body).append($rootElement);
24492467
};
24502468
}));
24512469

0 commit comments

Comments
 (0)