Skip to content

Commit ed3d1f2

Browse files
fix(core): Fix cancellation of animation enter classes (angular#63442)
When toggling visibility on an element over and over, the enter animations were supposed to be cancelled and then the classes removed. There was a race condition happening that resulted in the cancelled animation being the leave animation. Rather than using the animation.cancel functionality, it's safer to just remove the enter classes. fixes: angular#63439 PR Close angular#63442
1 parent 99cf028 commit ed3d1f2

File tree

1 file changed

+11
-28
lines changed

1 file changed

+11
-28
lines changed

packages/core/src/render3/instructions/animation.ts

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ export function ɵɵanimateEnter(value: string | Function): typeof ɵɵanimateEn
182182
// This also allows us to setup cancellation of animations in progress if the
183183
// gets removed early.
184184
const handleAnimationStart = (event: AnimationEvent | TransitionEvent) => {
185-
setupAnimationCancel(event, renderer);
186185
const eventName = event instanceof AnimationEvent ? 'animationend' : 'transitionend';
187186
ngZone.runOutsideAngular(() => {
188187
cleanupFns.push(renderer.listen(nativeElement, eventName, handleInAnimationEnd));
@@ -449,40 +448,24 @@ function getClassList(value: Set<string> | null, resolvers: Function[] | undefin
449448
function cancelAnimationsIfRunning(element: HTMLElement, renderer: Renderer): void {
450449
if (!areAnimationSupported) return;
451450
const elementData = enterClassMap.get(element);
452-
if (element.getAnimations().length > 0) {
453-
for (const animation of element.getAnimations()) {
454-
if (animation.playState === 'running') {
455-
animation.cancel();
456-
}
457-
}
458-
} else {
459-
if (elementData) {
460-
for (const klass of elementData.classList) {
461-
renderer.removeClass(element as unknown as RElement, klass);
462-
}
451+
if (
452+
elementData &&
453+
elementData.classList.length > 0 &&
454+
elementHasClassList(element, elementData.classList)
455+
) {
456+
for (const klass of elementData.classList) {
457+
renderer.removeClass(element as unknown as RElement, klass);
463458
}
464459
}
465460
// We need to prevent any enter animation listeners from firing if they exist.
466461
cleanupEnterClassData(element);
467462
}
468463

469-
function setupAnimationCancel(event: Event, renderer: Renderer) {
470-
if (!(event.target instanceof Element)) return;
471-
const nativeElement = event.target;
472-
if (areAnimationSupported) {
473-
const elementData = enterClassMap.get(nativeElement as HTMLElement);
474-
const animations = nativeElement.getAnimations();
475-
if (animations.length === 0) return;
476-
for (let animation of animations) {
477-
animation.addEventListener('cancel', (event: Event) => {
478-
if (nativeElement === event.target && elementData?.classList) {
479-
for (const klass of elementData.classList) {
480-
renderer.removeClass(nativeElement as unknown as RElement, klass);
481-
}
482-
}
483-
});
484-
}
464+
function elementHasClassList(element: HTMLElement, classList: string[]): boolean {
465+
for (const className of classList) {
466+
if (element.classList.contains(className)) return true;
485467
}
468+
return false;
486469
}
487470

488471
function isLongestAnimation(

0 commit comments

Comments
 (0)