fix(animations): do not retain deleted nodes during an non-removal animation (#17153)
Closes #17086
This commit is contained in:
		
							parent
							
								
									598fdad089
								
							
						
					
					
						commit
						068133ec85
					
				| @ -872,22 +872,7 @@ export class TransitionAnimationEngine { | |||||||
|       if (players) { |       if (players) { | ||||||
|         optimizeGroupPlayer(players).onDone(fn); |         optimizeGroupPlayer(players).onDone(fn); | ||||||
|       } else { |       } else { | ||||||
|         let elementPlayers: AnimationPlayer[]|null = null; |         fn(); | ||||||
| 
 |  | ||||||
|         let parent = element; |  | ||||||
|         while (parent = parent.parentNode) { |  | ||||||
|           const playersForThisElement = this.playersByElement.get(parent); |  | ||||||
|           if (playersForThisElement && playersForThisElement.length) { |  | ||||||
|             elementPlayers = playersForThisElement; |  | ||||||
|             break; |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (elementPlayers) { |  | ||||||
|           optimizeGroupPlayer(elementPlayers).onDone(fn); |  | ||||||
|         } else { |  | ||||||
|           fn(); |  | ||||||
|         } |  | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1127,14 +1127,13 @@ export function main() { | |||||||
|         expect(count).toEqual(2); |         expect(count).toEqual(2); | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       it('should always make children wait for the parent animation to finish before any removals occur', |       it('should allow inner removals to happen when a non removal-based parent animation is set to animate', | ||||||
|          () => { |          () => { | ||||||
|            @Component({ |            @Component({ | ||||||
|              selector: 'ani-cmp', |              selector: 'ani-cmp', | ||||||
|              template: ` |              template: ` | ||||||
|             <div #parent [@parent]="exp1" class="parent"> |             <div #parent [@parent]="exp1" class="parent"> | ||||||
|               <div #child1 *ngIf="exp2" class="child1"></div> |               <div #child *ngIf="exp2" class="child"></div> | ||||||
|               <div #child2 *ngIf="exp2" class="child2"></div> |  | ||||||
|             </div> |             </div> | ||||||
|           `,
 |           `,
 | ||||||
|              animations: [trigger( |              animations: [trigger( | ||||||
| @ -1148,9 +1147,7 @@ export function main() { | |||||||
| 
 | 
 | ||||||
|              @ViewChild('parent') public parent: any; |              @ViewChild('parent') public parent: any; | ||||||
| 
 | 
 | ||||||
|              @ViewChild('child1') public child1Elm: any; |              @ViewChild('child') public child: any; | ||||||
| 
 |  | ||||||
|              @ViewChild('child2') public child2Elm: any; |  | ||||||
|            } |            } | ||||||
| 
 | 
 | ||||||
|            TestBed.configureTestingModule({declarations: [Cmp]}); |            TestBed.configureTestingModule({declarations: [Cmp]}); | ||||||
| @ -1170,10 +1167,69 @@ export function main() { | |||||||
|            engine.flush(); |            engine.flush(); | ||||||
| 
 | 
 | ||||||
|            const player = getLog()[0]; |            const player = getLog()[0]; | ||||||
|  |            const p = cmp.parent.nativeElement; | ||||||
|  |            const c = cmp.child.nativeElement; | ||||||
|  | 
 | ||||||
|  |            expect(p.contains(c)).toBeTruthy(); | ||||||
|  | 
 | ||||||
|  |            cmp.exp2 = false; | ||||||
|  |            fixture.detectChanges(); | ||||||
|  |            engine.flush(); | ||||||
|  | 
 | ||||||
|  |            expect(p.contains(c)).toBeFalsy(); | ||||||
|  | 
 | ||||||
|  |            player.finish(); | ||||||
|  | 
 | ||||||
|  |            expect(p.contains(c)).toBeFalsy(); | ||||||
|  |          }); | ||||||
|  | 
 | ||||||
|  |       it('should make inner removals wait until a parent based removal animation has finished', | ||||||
|  |          () => { | ||||||
|  |            @Component({ | ||||||
|  |              selector: 'ani-cmp', | ||||||
|  |              template: ` | ||||||
|  |             <div #parent *ngIf="exp1" @parent class="parent"> | ||||||
|  |               <div #child1 *ngIf="exp2" class="child1"></div> | ||||||
|  |               <div #child2 *ngIf="exp2" class="child2"></div> | ||||||
|  |             </div> | ||||||
|  |           `,
 | ||||||
|  |              animations: [trigger( | ||||||
|  |                  'parent', | ||||||
|  |                  [transition( | ||||||
|  |                      ':leave', [style({opacity: 0}), animate(1000, style({opacity: 1}))])])] | ||||||
|  |            }) | ||||||
|  |            class Cmp { | ||||||
|  |              public exp1: any; | ||||||
|  |              public exp2: any; | ||||||
|  | 
 | ||||||
|  |              @ViewChild('parent') public parent: any; | ||||||
|  | 
 | ||||||
|  |              @ViewChild('child1') public child1Elm: any; | ||||||
|  | 
 | ||||||
|  |              @ViewChild('child2') public child2Elm: any; | ||||||
|  |            } | ||||||
|  | 
 | ||||||
|  |            TestBed.configureTestingModule({declarations: [Cmp]}); | ||||||
|  | 
 | ||||||
|  |            const engine = TestBed.get(ɵAnimationEngine); | ||||||
|  |            const fixture = TestBed.createComponent(Cmp); | ||||||
|  |            const cmp = fixture.componentInstance; | ||||||
|  | 
 | ||||||
|  |            cmp.exp1 = true; | ||||||
|  |            cmp.exp2 = true; | ||||||
|  |            fixture.detectChanges(); | ||||||
|  |            engine.flush(); | ||||||
|  |            resetLog(); | ||||||
|  | 
 | ||||||
|            const p = cmp.parent.nativeElement; |            const p = cmp.parent.nativeElement; | ||||||
|            const c1 = cmp.child1Elm.nativeElement; |            const c1 = cmp.child1Elm.nativeElement; | ||||||
|            const c2 = cmp.child2Elm.nativeElement; |            const c2 = cmp.child2Elm.nativeElement; | ||||||
| 
 | 
 | ||||||
|  |            cmp.exp1 = false; | ||||||
|  |            cmp.exp2 = false; | ||||||
|  |            fixture.detectChanges(); | ||||||
|  |            engine.flush(); | ||||||
|  | 
 | ||||||
|            expect(p.contains(c1)).toBeTruthy(); |            expect(p.contains(c1)).toBeTruthy(); | ||||||
|            expect(p.contains(c2)).toBeTruthy(); |            expect(p.contains(c2)).toBeTruthy(); | ||||||
| 
 | 
 | ||||||
| @ -1183,11 +1239,6 @@ export function main() { | |||||||
| 
 | 
 | ||||||
|            expect(p.contains(c1)).toBeTruthy(); |            expect(p.contains(c1)).toBeTruthy(); | ||||||
|            expect(p.contains(c2)).toBeTruthy(); |            expect(p.contains(c2)).toBeTruthy(); | ||||||
| 
 |  | ||||||
|            player.finish(); |  | ||||||
| 
 |  | ||||||
|            expect(p.contains(c1)).toBeFalsy(); |  | ||||||
|            expect(p.contains(c2)).toBeFalsy(); |  | ||||||
|          }); |          }); | ||||||
| 
 | 
 | ||||||
|       it('should substitute in values if the provided state match is an object with values', () => { |       it('should substitute in values if the provided state match is an object with values', () => { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user