diff --git a/packages/animations/browser/src/dsl/animation_timeline_builder.ts b/packages/animations/browser/src/dsl/animation_timeline_builder.ts index 25872f9050..2c29d9e071 100644 --- a/packages/animations/browser/src/dsl/animation_timeline_builder.ts +++ b/packages/animations/browser/src/dsl/animation_timeline_builder.ts @@ -454,27 +454,28 @@ export class AnimationTimelineContext { updateOptions(options: AnimationOptions|null, skipIfExists?: boolean) { if (!options) return; - // NOTE: this will get patched up when other animation methods support duration overrides const newOptions = options as any; + let optionsToUpdate = this.options; + + // NOTE: this will get patched up when other animation methods support duration overrides if (newOptions.duration != null) { - (this.options as any).duration = resolveTimingValue(newOptions.duration); + (optionsToUpdate as any).duration = resolveTimingValue(newOptions.duration); } if (newOptions.delay != null) { - this.options.delay = resolveTimingValue(newOptions.delay); + optionsToUpdate.delay = resolveTimingValue(newOptions.delay); } const newParams = newOptions.params; if (newParams) { - let params: {[name: string]: any} = this.options && this.options.params !; - if (!params) { - params = this.options.params = {}; + let paramsToUpdate: {[name: string]: any} = optionsToUpdate.params !; + if (!paramsToUpdate) { + paramsToUpdate = this.options.params = {}; } - Object.keys(params).forEach(name => { - const value = params[name]; - if (!skipIfExists || !newOptions.hasOwnProperty(name)) { - params[name] = value; + Object.keys(newParams).forEach(name => { + if (!skipIfExists || !paramsToUpdate.hasOwnProperty(name)) { + paramsToUpdate[name] = newParams[name]; } }); } diff --git a/packages/animations/browser/test/dsl/animation_spec.ts b/packages/animations/browser/test/dsl/animation_spec.ts index 56d3590bb2..4387bb3e89 100644 --- a/packages/animations/browser/test/dsl/animation_spec.ts +++ b/packages/animations/browser/test/dsl/animation_spec.ts @@ -5,7 +5,7 @@ * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -import {AUTO_STYLE, AnimationMetadata, AnimationMetadataType, animate, group, keyframes, query, sequence, style, ɵStyleData} from '@angular/animations'; +import {AUTO_STYLE, AnimationMetadata, AnimationMetadataType, animate, animation, group, keyframes, query, sequence, style, useAnimation, ɵStyleData} from '@angular/animations'; import {AnimationOptions} from '@angular/core/src/animation/dsl'; import {Animation} from '../../src/dsl/animation'; @@ -304,10 +304,31 @@ export function main() { }); describe('subtitutions', () => { + it('should allow params to be subtituted even if they are not defaulted in a reusable animation', + () => { + const myAnimation = animation([ + style({left: '{{ start }}'}), + animate(1000, style({left: '{{ end }}'})), + ]); + + const steps = [ + useAnimation(myAnimation, {params: {start: '0px', end: '100px'}}), + ]; + + const players = invokeAnimationSequence(rootElement, steps, {}); + expect(players.length).toEqual(1); + const player = players[0]; + + expect(player.keyframes).toEqual([ + {left: '0px', offset: 0}, + {left: '100px', offset: 1}, + ]); + }); + it('should substitute in timing values', () => { - function makeAnimation(exp: string, values: {[key: string]: any}) { + function makeAnimation(exp: string, options: {[key: string]: any}) { const steps = [style({opacity: 0}), animate(exp, style({opacity: 1}))]; - return invokeAnimationSequence(rootElement, steps, values); + return invokeAnimationSequence(rootElement, steps, options); } let players = makeAnimation('{{ duration }}', buildParams({duration: '1234ms'}));