From 590d93b30dfb0fcc6baf380bc155dd07dd121f46 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matias=20Niemel=C3=A4?= <matias@yearofmoo.com>
Date: Thu, 30 Nov 2017 16:15:48 -0800
Subject: [PATCH] feat(animations): re-introduce support for transition
 matching functions (#20723)

Closes #18959

PR Close #20723
---
 packages/animations/src/animation_metadata.ts |  5 ++-
 .../animation/animation_integration_spec.ts   | 39 +++++++++++++++++++
 .../animations/animations.d.ts                |  4 +-
 3 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/packages/animations/src/animation_metadata.ts b/packages/animations/src/animation_metadata.ts
index 3d436a2743..15b6e4b007 100755
--- a/packages/animations/src/animation_metadata.ts
+++ b/packages/animations/src/animation_metadata.ts
@@ -115,7 +115,7 @@ export interface AnimationStateMetadata extends AnimationMetadata {
  * @experimental Animation support is experimental.
  */
 export interface AnimationTransitionMetadata extends AnimationMetadata {
-  expr: string;
+  expr: string|((fromState: string, toState: string) => boolean);
   animation: AnimationMetadata|AnimationMetadata[];
   options: AnimationOptions|null;
 }
@@ -836,7 +836,8 @@ export function keyframes(steps: AnimationStyleMetadata[]): AnimationKeyframesSe
  * @experimental Animation support is experimental.
  */
 export function transition(
-    stateChangeExpr: string, steps: AnimationMetadata | AnimationMetadata[],
+    stateChangeExpr: string | ((fromState: string, toState: string) => boolean),
+    steps: AnimationMetadata | AnimationMetadata[],
     options: AnimationOptions | null = null): AnimationTransitionMetadata {
   return {type: AnimationMetadataType.Transition, expr: stateChangeExpr, animation: steps, options};
 }
diff --git a/packages/core/test/animation/animation_integration_spec.ts b/packages/core/test/animation/animation_integration_spec.ts
index 1e0dcf40a2..e01d6065b5 100644
--- a/packages/core/test/animation/animation_integration_spec.ts
+++ b/packages/core/test/animation/animation_integration_spec.ts
@@ -255,6 +255,45 @@ export function main() {
         ]);
       });
 
+      it('should allow a transition to use a function to determine what method to run', () => {
+        let valueToMatch = '';
+        const transitionFn =
+            (fromState: string, toState: string) => { return toState == valueToMatch; };
+
+        @Component({
+          selector: 'if-cmp',
+          template: '<div [@myAnimation]="exp"></div>',
+          animations: [
+            trigger('myAnimation', [transition(
+                                       transitionFn,
+                                       [style({opacity: 0}), animate(1234, style({opacity: 1}))])]),
+          ]
+        })
+        class Cmp {
+          exp: any = '';
+        }
+
+        TestBed.configureTestingModule({declarations: [Cmp]});
+
+        const fixture = TestBed.createComponent(Cmp);
+        const cmp = fixture.componentInstance;
+        valueToMatch = cmp.exp = 'something';
+        fixture.detectChanges();
+
+        let players = getLog();
+        expect(players.length).toEqual(1);
+        let [p1] = players;
+        expect(p1.totalTime).toEqual(1234);
+        resetLog();
+
+        valueToMatch = 'something-else';
+        cmp.exp = 'this-wont-match';
+        fixture.detectChanges();
+
+        players = getLog();
+        expect(players.length).toEqual(0);
+      });
+
       it('should allow a state value to be `0`', () => {
         @Component({
           selector: 'if-cmp',
diff --git a/tools/public_api_guard/animations/animations.d.ts b/tools/public_api_guard/animations/animations.d.ts
index 45dd78afa3..a302384103 100644
--- a/tools/public_api_guard/animations/animations.d.ts
+++ b/tools/public_api_guard/animations/animations.d.ts
@@ -172,7 +172,7 @@ export interface AnimationStyleMetadata extends AnimationMetadata {
 /** @experimental */
 export interface AnimationTransitionMetadata extends AnimationMetadata {
     animation: AnimationMetadata | AnimationMetadata[];
-    expr: string;
+    expr: string | ((fromState: string, toState: string) => boolean);
     options: AnimationOptions | null;
 }
 
@@ -240,7 +240,7 @@ export declare function style(tokens: '*' | {
 }>): AnimationStyleMetadata;
 
 /** @experimental */
-export declare function transition(stateChangeExpr: string, steps: AnimationMetadata | AnimationMetadata[], options?: AnimationOptions | null): AnimationTransitionMetadata;
+export declare function transition(stateChangeExpr: string | ((fromState: string, toState: string) => boolean), steps: AnimationMetadata | AnimationMetadata[], options?: AnimationOptions | null): AnimationTransitionMetadata;
 
 /** @experimental */
 export declare function trigger(name: string, definitions: AnimationMetadata[]): AnimationTriggerMetadata;