@@ -88,12 +88,30 @@ const longestAnimations = new WeakMap<HTMLElement, LongestAnimation>();
8888// from an `@if` or `@for`.
8989const leavingNodes = new WeakMap < TNode , HTMLElement [ ] > ( ) ;
9090
91- function clearLeavingNodes ( tNode : TNode ) : void {
92- if ( leavingNodes . get ( tNode ) ?. length === 0 ) {
91+ function clearLeavingNodes ( tNode : TNode , el : HTMLElement ) : void {
92+ const nodes = leavingNodes . get ( tNode ) ;
93+ if ( nodes && nodes . length > 0 ) {
94+ const ix = nodes . findIndex ( ( node ) => node === el ) ;
95+ if ( ix > - 1 ) nodes . splice ( ix , 1 ) ;
96+ }
97+ if ( nodes ?. length === 0 ) {
9398 leavingNodes . delete ( tNode ) ;
9499 }
95100}
96101
102+ /**
103+ * In the case that we have an existing node that's animating away, like when
104+ * an `@if` toggles quickly or `@for` adds and removes elements quickly, we
105+ * need to end the animation for the former node and remove it right away to
106+ * prevent duplicate nodes showing up.
107+ */
108+ function cancelLeavingNodes ( tNode : TNode , el : HTMLElement ) : void {
109+ leavingNodes
110+ . get ( tNode )
111+ ?. pop ( )
112+ ?. dispatchEvent ( new CustomEvent ( 'animationend' , { detail : { cancel : true } } ) ) ;
113+ }
114+
97115function trackLeavingNodes ( tNode : TNode , el : HTMLElement ) : void {
98116 // We need to track this tNode's element just to be sure we don't add
99117 // a new RNode for this TNode while this one is still animating away.
@@ -160,15 +178,6 @@ export function ɵɵanimateEnter(value: string | Function): typeof ɵɵanimateEn
160178 cleanupFns . push ( renderer . listen ( nativeElement , 'transitionstart' , handleAnimationStart ) ) ;
161179 } ) ;
162180
163- // In the case that we have an existing node that's animating away, like when
164- // an `@if` toggles quickly or `@for` adds and removes elements quickly, we
165- // need to end the animation for the former node and remove it right away to
166- // prevent duplicate nodes showing up.
167- leavingNodes
168- . get ( tNode )
169- ?. pop ( )
170- ?. dispatchEvent ( new CustomEvent ( 'animationend' , { detail : { cancel : true } } ) ) ;
171-
172181 trackEnterClasses ( nativeElement , activeClasses , cleanupFns ) ;
173182
174183 for ( const klass of activeClasses ) {
@@ -179,6 +188,12 @@ export function ɵɵanimateEnter(value: string | Function): typeof ɵɵanimateEn
179188 // preventing an animation via selector specificity.
180189 ngZone . runOutsideAngular ( ( ) => {
181190 requestAnimationFrame ( ( ) => {
191+ // In the case that we have an existing node that's animating away, like when
192+ // an `@if` toggles quickly or `@for` adds and removes elements quickly, we
193+ // need to end the animation for the former node and remove it right away to
194+ // prevent duplicate nodes showing up.
195+ cancelLeavingNodes ( tNode , nativeElement ) ;
196+
182197 determineLongestAnimation ( nativeElement , longestAnimations , areAnimationSupported ) ;
183198 if ( ! longestAnimations . has ( nativeElement ) ) {
184199 for ( const klass of activeClasses ) {
@@ -242,10 +257,7 @@ export function ɵɵanimateEnterListener(value: AnimationFunction): typeof ɵɵa
242257 // an `@if` toggles quickly or `@for` adds and removes elements quickly, we
243258 // need to end the animation for the former node and remove it right away to
244259 // prevent duplicate nodes showing up.
245- leavingNodes
246- . get ( tNode )
247- ?. pop ( )
248- ?. dispatchEvent ( new CustomEvent ( 'animationend' , { detail : { cancel : true } } ) ) ;
260+ cancelLeavingNodes ( tNode , nativeElement ) ;
249261
250262 value . call ( lView [ CONTEXT ] , { target : nativeElement , animationComplete : noOpAnimationComplete } ) ;
251263
@@ -375,7 +387,7 @@ export function ɵɵanimateLeaveListener(value: AnimationFunction): typeof ɵɵa
375387 const event : AnimationCallbackEvent = {
376388 target : nativeElement ,
377389 animationComplete : ( ) => {
378- clearLeavingNodes ( tNode ) ;
390+ clearLeavingNodes ( tNode , _el as HTMLElement ) ;
379391 removeFn ( ) ;
380392 } ,
381393 } ;
@@ -530,7 +542,7 @@ function animateLeaveClassRunner(
530542 // affect any other animations on the page.
531543 event . stopImmediatePropagation ( ) ;
532544 longestAnimations . delete ( el ) ;
533- clearLeavingNodes ( tNode ) ;
545+ clearLeavingNodes ( tNode , el ) ;
534546 finalRemoveFn ( ) ;
535547 }
536548 } ;
@@ -550,7 +562,7 @@ function animateLeaveClassRunner(
550562 requestAnimationFrame ( ( ) => {
551563 determineLongestAnimation ( el , longestAnimations , areAnimationSupported ) ;
552564 if ( ! longestAnimations . has ( el ) ) {
553- clearLeavingNodes ( tNode ) ;
565+ clearLeavingNodes ( tNode , el ) ;
554566 finalRemoveFn ( ) ;
555567 }
556568 } ) ;
0 commit comments