feat(animations): expose element and params within transition matchers (#22693)
				
					
				
			PR Close #22693
This commit is contained in:
		
							parent
							
								
									db56836425
								
							
						
					
					
						commit
						58b94e6f5e
					
				| @ -46,7 +46,8 @@ export interface StateAst extends Ast<AnimationMetadataType.State> { | ||||
| } | ||||
| 
 | ||||
| export interface TransitionAst extends Ast<AnimationMetadataType.Transition> { | ||||
|   matchers: ((fromState: string, toState: string) => boolean)[]; | ||||
|   matchers: ((fromState: string, toState: string, element: any, params: {[key: string]: | ||||
|                                                                              any}) => boolean)[]; | ||||
|   animation: Ast<AnimationMetadataType>; | ||||
|   queryCount: number; | ||||
|   depCount: number; | ||||
|  | ||||
| @ -6,7 +6,8 @@ | ||||
|  * found in the LICENSE file at https://angular.io/license
 | ||||
|  */ | ||||
| export const ANY_STATE = '*'; | ||||
| export declare type TransitionMatcherFn = (fromState: any, toState: any) => boolean; | ||||
| export declare type TransitionMatcherFn = | ||||
|     (fromState: any, toState: any, element: any, params: {[key: string]: any}) => boolean; | ||||
| 
 | ||||
| export function parseTransitionExpr( | ||||
|     transitionValue: string | TransitionMatcherFn, errors: string[]): TransitionMatcherFn[] { | ||||
|  | ||||
| @ -24,8 +24,8 @@ export class AnimationTransitionFactory { | ||||
|       private _triggerName: string, public ast: TransitionAst, | ||||
|       private _stateStyles: {[stateName: string]: AnimationStateStyles}) {} | ||||
| 
 | ||||
|   match(currentState: any, nextState: any): boolean { | ||||
|     return oneOrMoreTransitionsMatch(this.ast.matchers, currentState, nextState); | ||||
|   match(currentState: any, nextState: any, element: any, params: {[key: string]: any}): boolean { | ||||
|     return oneOrMoreTransitionsMatch(this.ast.matchers, currentState, nextState, element, params); | ||||
|   } | ||||
| 
 | ||||
|   buildStyles(stateName: string, params: {[key: string]: any}, errors: any[]) { | ||||
| @ -89,8 +89,9 @@ export class AnimationTransitionFactory { | ||||
| } | ||||
| 
 | ||||
| function oneOrMoreTransitionsMatch( | ||||
|     matchFns: TransitionMatcherFn[], currentState: any, nextState: any): boolean { | ||||
|   return matchFns.some(fn => fn(currentState, nextState)); | ||||
|     matchFns: TransitionMatcherFn[], currentState: any, nextState: any, element: any, | ||||
|     params: {[key: string]: any}): boolean { | ||||
|   return matchFns.some(fn => fn(currentState, nextState, element, params)); | ||||
| } | ||||
| 
 | ||||
| export class AnimationStateStyles { | ||||
|  | ||||
| @ -47,8 +47,10 @@ export class AnimationTrigger { | ||||
| 
 | ||||
|   get containsQueries() { return this.ast.queryCount > 0; } | ||||
| 
 | ||||
|   matchTransition(currentState: any, nextState: any): AnimationTransitionFactory|null { | ||||
|     const entry = this.transitionFactories.find(f => f.match(currentState, nextState)); | ||||
|   matchTransition(currentState: any, nextState: any, element: any, params: {[key: string]: any}): | ||||
|       AnimationTransitionFactory|null { | ||||
|     const entry = | ||||
|         this.transitionFactories.find(f => f.match(currentState, nextState, element, params)); | ||||
|     return entry || null; | ||||
|   } | ||||
| 
 | ||||
|  | ||||
| @ -248,7 +248,8 @@ export class AnimationTransitionNamespace { | ||||
|       } | ||||
|     }); | ||||
| 
 | ||||
|     let transition = trigger.matchTransition(fromState.value, toState.value); | ||||
|     let transition = | ||||
|         trigger.matchTransition(fromState.value, toState.value, element, toState.params); | ||||
|     let isFallbackTransition = false; | ||||
|     if (!transition) { | ||||
|       if (!defaultToFallback) return; | ||||
|  | ||||
| @ -103,7 +103,7 @@ import {makeTrigger} from '../shared'; | ||||
|       it('should null when no results are found', () => { | ||||
|         const result = makeTrigger('name', [transition('a => b', animate(1111))]); | ||||
| 
 | ||||
|         const trigger = result.matchTransition('b', 'a'); | ||||
|         const trigger = result.matchTransition('b', 'a', {}, {}); | ||||
|         expect(trigger).toBeFalsy(); | ||||
|       }); | ||||
| 
 | ||||
| @ -226,7 +226,8 @@ function buildTransition( | ||||
|     trigger: AnimationTrigger, element: any, fromState: any, toState: any, | ||||
|     fromOptions?: AnimationOptions, toOptions?: AnimationOptions): AnimationTransitionInstruction| | ||||
|     null { | ||||
|   const trans = trigger.matchTransition(fromState, toState) !; | ||||
|   const params = toOptions && toOptions.params || {}; | ||||
|   const trans = trigger.matchTransition(fromState, toState, element, params) !; | ||||
|   if (trans) { | ||||
|     const driver = new MockAnimationDriver(); | ||||
|     return trans.build( | ||||
|  | ||||
| @ -115,7 +115,9 @@ export interface AnimationStateMetadata extends AnimationMetadata { | ||||
|  * @experimental Animation support is experimental. | ||||
|  */ | ||||
| export interface AnimationTransitionMetadata extends AnimationMetadata { | ||||
|   expr: string|((fromState: string, toState: string) => boolean); | ||||
|   expr: string| | ||||
|       ((fromState: string, toState: string, element?: any, | ||||
|         params?: {[key: string]: any}) => boolean); | ||||
|   animation: AnimationMetadata|AnimationMetadata[]; | ||||
|   options: AnimationOptions|null; | ||||
| } | ||||
| @ -294,6 +296,38 @@ export interface AnimationStaggerMetadata extends AnimationMetadata { | ||||
|  * <div [@myAnimationTrigger]="myStatusExp">...</div> | ||||
|  * ``` | ||||
|  * | ||||
|  * ### Using an inline function | ||||
|  * The `transition` animation method also supports reading an inline function which can decide | ||||
|  * if its associated animation should be run. | ||||
|  * | ||||
|  * ``` | ||||
|  * // this method will be run each time the `myAnimationTrigger`
 | ||||
|  * // trigger value changes...
 | ||||
|  * function myInlineMatcherFn(fromState: string, toState: string, element: any, params: {[key: | ||||
|  string]: any}): boolean { | ||||
|  *   // notice that `element` and `params` are also available here
 | ||||
|  *   return toState == 'yes-please-animate'; | ||||
|  * } | ||||
|  * | ||||
|  * @Component({ | ||||
|  *   selector: 'my-component', | ||||
|  *   templateUrl: 'my-component-tpl.html', | ||||
|  *   animations: [ | ||||
|  *     trigger('myAnimationTrigger', [ | ||||
|  *       transition(myInlineMatcherFn, [ | ||||
|  *         // the animation sequence code
 | ||||
|  *       ]), | ||||
|  *     ]) | ||||
|  *   ] | ||||
|  * }) | ||||
|  * class MyComponent { | ||||
|  *   myStatusExp = "yes-please-animate"; | ||||
|  * } | ||||
|  * ``` | ||||
|  * | ||||
|  * The inline method will be run each time the trigger | ||||
|  * value changes | ||||
|  * | ||||
|  * ## Disable Animations | ||||
|  * A special animation control binding called `@.disabled` can be placed on an element which will | ||||
|  then disable animations for any inner animation triggers situated within the element as well as | ||||
| @ -844,7 +878,8 @@ export function keyframes(steps: AnimationStyleMetadata[]): AnimationKeyframesSe | ||||
|  * @experimental Animation support is experimental. | ||||
|  */ | ||||
| export function transition( | ||||
|     stateChangeExpr: string | ((fromState: string, toState: string) => boolean), | ||||
|     stateChangeExpr: string | ((fromState: string, toState: string, element?: any, | ||||
|                                 params?: {[key: string]: any}) => boolean), | ||||
|     steps: AnimationMetadata | AnimationMetadata[], | ||||
|     options: AnimationOptions | null = null): AnimationTransitionMetadata { | ||||
|   return {type: AnimationMetadataType.Transition, expr: stateChangeExpr, animation: steps, options}; | ||||
|  | ||||
| @ -38,7 +38,8 @@ export interface AnimationStateMetadata extends AnimationMetadata { | ||||
|  * @deprecated This symbol has moved. Please Import from @angular/animations instead! | ||||
|  */ | ||||
| export interface AnimationTransitionMetadata extends AnimationMetadata { | ||||
|   expr: string|((fromState: string, toState: string) => boolean); | ||||
|   expr: string| | ||||
|       ((fromState: string, toState: string, element: any, params: {[key: string]: any}) => boolean); | ||||
|   animation: AnimationMetadata|AnimationMetadata[]; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -301,12 +301,15 @@ const DEFAULT_COMPONENT_ID = '1'; | ||||
| 
 | ||||
|       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; }; | ||||
|         let capturedElement: any; | ||||
|         const transitionFn = (fromState: string, toState: string, element: any) => { | ||||
|           capturedElement = element; | ||||
|           return toState == valueToMatch; | ||||
|         }; | ||||
| 
 | ||||
|         @Component({ | ||||
|           selector: 'if-cmp', | ||||
|           template: '<div [@myAnimation]="exp"></div>', | ||||
|           template: '<div #element [@myAnimation]="exp"></div>', | ||||
|           animations: [ | ||||
|             trigger('myAnimation', [transition( | ||||
|                                        transitionFn, | ||||
| @ -314,6 +317,8 @@ const DEFAULT_COMPONENT_ID = '1'; | ||||
|           ] | ||||
|         }) | ||||
|         class Cmp { | ||||
|           @ViewChild('element') | ||||
|           element: any; | ||||
|           exp: any = ''; | ||||
|         } | ||||
| 
 | ||||
| @ -323,11 +328,13 @@ const DEFAULT_COMPONENT_ID = '1'; | ||||
|         const cmp = fixture.componentInstance; | ||||
|         valueToMatch = cmp.exp = 'something'; | ||||
|         fixture.detectChanges(); | ||||
|         const element = cmp.element.nativeElement; | ||||
| 
 | ||||
|         let players = getLog(); | ||||
|         expect(players.length).toEqual(1); | ||||
|         let [p1] = players; | ||||
|         expect(p1.totalTime).toEqual(1234); | ||||
|         expect(capturedElement).toEqual(element); | ||||
|         resetLog(); | ||||
| 
 | ||||
|         valueToMatch = 'something-else'; | ||||
| @ -338,6 +345,49 @@ const DEFAULT_COMPONENT_ID = '1'; | ||||
|         expect(players.length).toEqual(0); | ||||
|       }); | ||||
| 
 | ||||
|       it('should allow a transition to use a function to determine what method to run and expose any parameter values', | ||||
|          () => { | ||||
|            const transitionFn = | ||||
|                (fromState: string, toState: string, element: any, params: {[key: string]: any}) => { | ||||
|                  return params['doMatch'] == true; | ||||
|                }; | ||||
| 
 | ||||
|            @Component({ | ||||
|              selector: 'if-cmp', | ||||
|              template: '<div [@myAnimation]="{value:exp, params: {doMatch:doMatch}}"></div>', | ||||
|              animations: [ | ||||
|                trigger( | ||||
|                    'myAnimation', | ||||
|                    [transition( | ||||
|                        transitionFn, [style({opacity: 0}), animate(3333, style({opacity: 1}))])]), | ||||
|              ] | ||||
|            }) | ||||
|            class Cmp { | ||||
|              doMatch = false; | ||||
|              exp: any = ''; | ||||
|            } | ||||
| 
 | ||||
|            TestBed.configureTestingModule({declarations: [Cmp]}); | ||||
| 
 | ||||
|            const fixture = TestBed.createComponent(Cmp); | ||||
|            const cmp = fixture.componentInstance; | ||||
|            cmp.doMatch = true; | ||||
|            fixture.detectChanges(); | ||||
| 
 | ||||
|            let players = getLog(); | ||||
|            expect(players.length).toEqual(1); | ||||
|            let [p1] = players; | ||||
|            expect(p1.totalTime).toEqual(3333); | ||||
|            resetLog(); | ||||
| 
 | ||||
|            cmp.doMatch = false; | ||||
|            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', | ||||
|  | ||||
| @ -173,7 +173,9 @@ export interface AnimationStyleMetadata extends AnimationMetadata { | ||||
| /** @experimental */ | ||||
| export interface AnimationTransitionMetadata extends AnimationMetadata { | ||||
|     animation: AnimationMetadata | AnimationMetadata[]; | ||||
|     expr: string | ((fromState: string, toState: string) => boolean); | ||||
|     expr: string | ((fromState: string, toState: string, element?: any, params?: { | ||||
|         [key: string]: any; | ||||
|     }) => boolean); | ||||
|     options: AnimationOptions | null; | ||||
| } | ||||
| 
 | ||||
| @ -241,7 +243,9 @@ export declare function style(tokens: '*' | { | ||||
| }>): AnimationStyleMetadata; | ||||
| 
 | ||||
| /** @experimental */ | ||||
| export declare function transition(stateChangeExpr: string | ((fromState: string, toState: string) => boolean), steps: AnimationMetadata | AnimationMetadata[], options?: AnimationOptions | null): AnimationTransitionMetadata; | ||||
| export declare function transition(stateChangeExpr: string | ((fromState: string, toState: string, element?: any, params?: { | ||||
|     [key: string]: any; | ||||
| }) => boolean), steps: AnimationMetadata | AnimationMetadata[], options?: AnimationOptions | null): AnimationTransitionMetadata; | ||||
| 
 | ||||
| /** @experimental */ | ||||
| export declare function trigger(name: string, definitions: AnimationMetadata[]): AnimationTriggerMetadata; | ||||
|  | ||||
							
								
								
									
										4
									
								
								tools/public_api_guard/core/core.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								tools/public_api_guard/core/core.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -94,7 +94,9 @@ export interface AnimationTransitionEvent { | ||||
| /** @deprecated */ | ||||
| export interface AnimationTransitionMetadata extends AnimationMetadata { | ||||
|     animation: AnimationMetadata | AnimationMetadata[]; | ||||
|     expr: string | ((fromState: string, toState: string) => boolean); | ||||
|     expr: string | ((fromState: string, toState: string, element: any, params: { | ||||
|         [key: string]: any; | ||||
|     }) => boolean); | ||||
| } | ||||
| 
 | ||||
| /** @deprecated */ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user