fix(animations): always change to desired animation state even if no transition fires (#17025)
Fixes #16947
This commit is contained in:
parent
c20f60b144
commit
665e7071fa
|
@ -734,8 +734,8 @@ export class TransitionAnimationEngine {
|
||||||
|
|
||||||
// if a unmatched transition is queued to go then it SHOULD NOT render
|
// if a unmatched transition is queued to go then it SHOULD NOT render
|
||||||
// an animation and cancel the previously running animations.
|
// an animation and cancel the previously running animations.
|
||||||
if (entry.isFallbackTransition && !instruction.isRemovalTransition) {
|
if (entry.isFallbackTransition) {
|
||||||
eraseStyles(element, instruction.fromStyles);
|
player.onStart(() => eraseStyles(element, instruction.fromStyles));
|
||||||
player.onDestroy(() => setStyles(element, instruction.toStyles));
|
player.onDestroy(() => setStyles(element, instruction.toStyles));
|
||||||
skippedPlayers.push(player);
|
skippedPlayers.push(player);
|
||||||
return;
|
return;
|
||||||
|
@ -790,6 +790,14 @@ export class TransitionAnimationEngine {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
skippedPlayers.forEach(player => {
|
||||||
|
const element = player.element;
|
||||||
|
const previousPlayers =
|
||||||
|
this._getPreviousPlayers(element, false, player.namespaceId, player.triggerName, null);
|
||||||
|
previousPlayers.forEach(
|
||||||
|
prevPlayer => { getOrSetAsInMap(allPreviousPlayersMap, element, []).push(prevPlayer); });
|
||||||
|
});
|
||||||
|
|
||||||
allPreviousPlayersMap.forEach(players => players.forEach(player => player.destroy()));
|
allPreviousPlayersMap.forEach(players => players.forEach(player => player.destroy()));
|
||||||
|
|
||||||
const leaveNodes: any[] = bodyNode && allPostStyleElements.size ?
|
const leaveNodes: any[] = bodyNode && allPostStyleElements.size ?
|
||||||
|
@ -919,8 +927,8 @@ export class TransitionAnimationEngine {
|
||||||
afterFlushAnimationsDone(callback: () => any) { this._whenQuietFns.push(callback); }
|
afterFlushAnimationsDone(callback: () => any) { this._whenQuietFns.push(callback); }
|
||||||
|
|
||||||
private _getPreviousPlayers(
|
private _getPreviousPlayers(
|
||||||
element: string, instruction: AnimationTransitionInstruction, isQueriedElement: boolean,
|
element: string, isQueriedElement: boolean, namespaceId?: string, triggerName?: string,
|
||||||
namespaceId?: string, triggerName?: string): TransitionAnimationPlayer[] {
|
toStateValue?: any): TransitionAnimationPlayer[] {
|
||||||
let players: TransitionAnimationPlayer[] = [];
|
let players: TransitionAnimationPlayer[] = [];
|
||||||
if (isQueriedElement) {
|
if (isQueriedElement) {
|
||||||
const queriedElementPlayers = this.playersByQueriedElement.get(element);
|
const queriedElementPlayers = this.playersByQueriedElement.get(element);
|
||||||
|
@ -930,10 +938,10 @@ export class TransitionAnimationEngine {
|
||||||
} else {
|
} else {
|
||||||
const elementPlayers = this.playersByElement.get(element);
|
const elementPlayers = this.playersByElement.get(element);
|
||||||
if (elementPlayers) {
|
if (elementPlayers) {
|
||||||
const isRemovalAnimation = instruction.toState == VOID_VALUE;
|
const isRemovalAnimation = !toStateValue || toStateValue == VOID_VALUE;
|
||||||
elementPlayers.forEach(player => {
|
elementPlayers.forEach(player => {
|
||||||
if (player.queued) return;
|
if (player.queued) return;
|
||||||
if (!isRemovalAnimation && player.triggerName != instruction.triggerName) return;
|
if (!isRemovalAnimation && player.triggerName != triggerName) return;
|
||||||
players.push(player);
|
players.push(player);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -943,7 +951,7 @@ export class TransitionAnimationEngine {
|
||||||
if (namespaceId && namespaceId != player.namespaceId) return false;
|
if (namespaceId && namespaceId != player.namespaceId) return false;
|
||||||
if (triggerName && triggerName != player.triggerName) return false;
|
if (triggerName && triggerName != player.triggerName) return false;
|
||||||
return true;
|
return true;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
return players;
|
return players;
|
||||||
}
|
}
|
||||||
|
@ -970,7 +978,7 @@ export class TransitionAnimationEngine {
|
||||||
const isQueriedElement = element !== rootElement;
|
const isQueriedElement = element !== rootElement;
|
||||||
const players = getOrSetAsInMap(allPreviousPlayersMap, element, []);
|
const players = getOrSetAsInMap(allPreviousPlayersMap, element, []);
|
||||||
const previousPlayers = this._getPreviousPlayers(
|
const previousPlayers = this._getPreviousPlayers(
|
||||||
element, instruction, isQueriedElement, targetNameSpaceId, targetTriggerName);
|
element, isQueriedElement, targetNameSpaceId, targetTriggerName, instruction.toState);
|
||||||
previousPlayers.forEach(player => {
|
previousPlayers.forEach(player => {
|
||||||
const realPlayer = player.getRealPlayer() as any;
|
const realPlayer = player.getRealPlayer() as any;
|
||||||
if (realPlayer.beforeDestroy) {
|
if (realPlayer.beforeDestroy) {
|
||||||
|
|
|
@ -223,7 +223,7 @@ export function main() {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not cancel the previous transition if a follow-up transition is not matched',
|
it('should always cancel the previous transition if a follow-up transition is not matched',
|
||||||
fakeAsync(() => {
|
fakeAsync(() => {
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'if-cmp',
|
selector: 'if-cmp',
|
||||||
|
@ -290,7 +290,7 @@ export function main() {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
engine.flush();
|
engine.flush();
|
||||||
|
|
||||||
expect(engine.players.length).toEqual(1);
|
expect(engine.players.length).toEqual(0);
|
||||||
expect(getLog().length).toEqual(0);
|
expect(getLog().length).toEqual(0);
|
||||||
|
|
||||||
flushMicrotasks();
|
flushMicrotasks();
|
||||||
|
@ -299,7 +299,7 @@ export function main() {
|
||||||
expect(cmp.startEvent.toState).toEqual('c');
|
expect(cmp.startEvent.toState).toEqual('c');
|
||||||
expect(cmp.startEvent.totalTime).toEqual(0);
|
expect(cmp.startEvent.totalTime).toEqual(0);
|
||||||
|
|
||||||
expect(completed).toBe(false);
|
expect(completed).toBe(true);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should only turn a view removal as into `void` state transition', () => {
|
it('should only turn a view removal as into `void` state transition', () => {
|
||||||
|
|
|
@ -984,7 +984,7 @@ export function main() {
|
||||||
expect(count).toEqual(8);
|
expect(count).toEqual(8);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not cancel inner queried animations if a trigger state value changes, but isn\'t detected as a valid transition',
|
it('should cancel inner queried animations if a trigger state value changes, but isn\'t detected as a valid transition',
|
||||||
() => {
|
() => {
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ani-cmp',
|
selector: 'ani-cmp',
|
||||||
|
@ -1031,7 +1031,7 @@ export function main() {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
engine.flush();
|
engine.flush();
|
||||||
|
|
||||||
expect(count).toEqual(0);
|
expect(count).toEqual(5);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow for queried items to restore their styling back to the original state via animate(time, "*")',
|
it('should allow for queried items to restore their styling back to the original state via animate(time, "*")',
|
||||||
|
|
Loading…
Reference in New Issue