Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit d24617b

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 in such cases. 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). Partly addresses #14074 and #14124. Fixes #15510 Closes #15514
1 parent 2b7a359 commit d24617b

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-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

+22-2
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,28 @@ 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', function() {
465+
return {templateUrl: 'foo.html'};
466+
});
467+
});
468+
469+
inject(function($animate, $compile, $rootScope, $templateCache) {
470+
parent.append(jqLite('<foo ng-if="showFoo"></foo>'));
471+
$templateCache.put('foo.html', '<div>FOO</div>');
472+
$compile(parent)($rootScope);
473+
474+
expect(capturedAnimation).toBeNull();
475+
476+
$rootScope.$apply('showFoo = true');
477+
478+
expect(parent.text()).toBe('parentFOO');
479+
expect(capturedAnimation[0].html()).toBe('<div>FOO</div>');
480+
expect(capturedAnimation[1]).toBe('enter');
481+
});
482+
});
483+
462484
it('enter() should issue an enter animation and fire the DOM operation right away before the animation kicks off', inject(function($animate, $rootScope) {
463485
expect(parent.children().length).toBe(0);
464486

@@ -2437,15 +2459,13 @@ describe('animations', function() {
24372459

24382460
return function($rootElement, $q, $animate, $$AnimateRunner, $document) {
24392461
defaultFakeAnimationRunner = new $$AnimateRunner();
2440-
$animate.enabled(true);
24412462

24422463
element = jqLite('<div class="element">element</div>');
24432464
parent = jqLite('<div class="parent1">parent</div>');
24442465
parent2 = jqLite('<div class="parent2">parent</div>');
24452466

24462467
$rootElement.append(parent);
24472468
$rootElement.append(parent2);
2448-
jqLite($document[0].body).append($rootElement);
24492469
};
24502470
}));
24512471

0 commit comments

Comments
 (0)