fix(animations): always change to desired animation state even if no transition fires (#17025)

Fixes #16947
This commit is contained in:
Matias Niemelä 2017-05-31 15:36:41 -07:00 committed by Victor Berchet
parent c20f60b144
commit 665e7071fa
3 changed files with 21 additions and 13 deletions

View File

@ -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) {

View File

@ -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', () => {

View File

@ -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, "*")',