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…
Reference in New Issue