Skip to content

Commit

Permalink
fix(animations): make sure non-transitioned leave operations cancel e…
Browse files Browse the repository at this point in the history
…xisting animations (#15254)

Closes #15213

PR Close #15254
  • Loading branch information
matsko authored and mhevery committed Mar 17, 2017
1 parent d0bc83c commit a6fb78e
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 4 deletions.
10 changes: 6 additions & 4 deletions packages/animations/browser/src/render/dom_animation_engine.ts
Expand Up @@ -28,7 +28,8 @@ export interface TriggerListenerTuple {
callback: (event: any) => any;
}

const MARKED_FOR_ANIMATION = 'ng-animate';
const MARKED_FOR_ANIMATION_CLASSNAME = 'ng-animating';
const MARKED_FOR_ANIMATION_SELECTOR = '.ng-animating';
const MARKED_FOR_REMOVAL = '$$ngRemove';

export class DomAnimationEngine {
Expand Down Expand Up @@ -92,6 +93,7 @@ export class DomAnimationEngine {
element[MARKED_FOR_REMOVAL] = true;
this._queuedRemovals.set(element, () => {});
}
this._onRemovalTransition(element).forEach(player => player.destroy());
domFn();
}

Expand Down Expand Up @@ -162,7 +164,7 @@ export class DomAnimationEngine {
// when a parent animation is set to trigger a removal we want to
// find all of the children that are currently animating and clear
// them out by destroying each of them.
const elms = element.querySelectorAll(MARKED_FOR_ANIMATION);
const elms = element.querySelectorAll(MARKED_FOR_ANIMATION_SELECTOR);
for (let i = 0; i < elms.length; i++) {
const elm = elms[i];
const activePlayers = this._activeElementAnimations.get(elm);
Expand Down Expand Up @@ -300,8 +302,8 @@ export class DomAnimationEngine {
this._queuedTransitionAnimations.push(tuple);
player.init();

element.classList.add(MARKED_FOR_ANIMATION);
player.onDone(() => { element.classList.remove(MARKED_FOR_ANIMATION); });
element.classList.add(MARKED_FOR_ANIMATION_CLASSNAME);
player.onDone(() => { element.classList.remove(MARKED_FOR_ANIMATION_CLASSNAME); });
}

private _flushQueuedAnimations() {
Expand Down
45 changes: 45 additions & 0 deletions packages/core/test/animation/animation_integration_spec.ts
Expand Up @@ -366,6 +366,51 @@ export function main() {
assertHasParent(element, false);
});

it('should properly cancel all existing animations when a removal occurs', () => {
@Component({
selector: 'ani-cmp',
template: `
<div *ngIf="exp" [@myAnimation]="exp"></div>
`,
animations: [
trigger(
'myAnimation',
[
transition(
'* => go', [style({width: '0px'}), animate(1000, style({width: '100px'}))]),
]),
]
})
class Cmp {
public exp: string;
}

TestBed.configureTestingModule({declarations: [Cmp]});

const engine = TestBed.get(ɵAnimationEngine);
const fixture = TestBed.createComponent(Cmp);
const cmp = fixture.componentInstance;
cmp.exp = 'go';
fixture.detectChanges();
engine.flush();
expect(getLog().length).toEqual(1);
const [player1] = getLog();
resetLog();

let finished = false;
player1.onDone(() => finished = true);

let destroyed = false;
player1.onDestroy(() => destroyed = true);

cmp.exp = null;
fixture.detectChanges();
engine.flush();

expect(finished).toBeTruthy();
expect(destroyed).toBeTruthy();
});

it('should not run inner child animations when a parent is set to be removed', () => {
@Component({
selector: 'ani-cmp',
Expand Down

0 comments on commit a6fb78e

Please sign in to comment.