angular: Can't pass parameters in template to animation

I have written a small animation which doesn’t do much

my-animations.ts

export const leavingTowardsTop =
    trigger('leavingTowardsTop', [
        transition(':leave', [
            style({position: 'relative'}),
            animate("250ms ease-in", keyframes([
                style({top: 0}),
                style({top: "{{topPixels}}"})
            ]))
        ], {params : { topPixels: "-3000px" }})
    ])

I have registered the animation in a component and in its template I am trying to do :

<div [@leavingTowardsTop]="{params : { topPixels: '-30px' }}"> which works but ignore the specified value for topPixels (so it still takes -3000) I also tried :

[@leavingTowardsTop]="{ pixels: '-30px' }"

but the -30 is still ignored

Am I missing something here ?

I am on Angular 4.4.6 for all modules.

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 5
  • Comments: 24 (4 by maintainers)

Most upvoted comments

Ich kehre zurück am 01.11.2017.

Ich werde Ihre Nachricht nach meiner Rückkehr beantworten. In dringenden Fällen senden Sie bitte eine Kopie Ihrer E-Mail für technische Angelegenheiten an entwicklung@arxes-tolina.de, ansonsten an info@arxes-tolina.de. Ein anderer Mitarbeiter wird sich dann Ihrer E-Mail annehmen.

Hinweis: Dies ist eine automatische Antwort auf Ihre Nachricht “[angular/angular] Can’t pass parameters in template to animation (#19866)” gesendet am 23.10.2017 11:09:32.

Diese ist die einzige Benachrichtigung, die Sie empfangen werden, während diese Person abwesend ist.

For anyone who reviews this in the future.

If using the :enter and :leave aliases in conjunction with an *ngIf directive, passing undefined to a first argument of value resolves the issue.

Ex:

// TRIGGER
export const myAnimTrigger = trigger('myAnim', [
  transition(':enter', [
    style({transform: 'translateX({{ from }})'}),
    animate('250ms')
  ], { params: { from: '0'}}),
  transition(':leave', [
    style({transform: 'translateX(0)'}),
    animate('250ms')
  ])
]);
// TEMPLATE
<div *ngIf="myConditional"
     [@myAnim]="{value: undefined, params: { from: '-50%' }}">
  {{ myTextValue }}
</div>

I was curious about this “value” needed for the params of trigger to be recognized.

So I did a deep dive into the source code of Angular animations and then animation-browser. And in fact, if you go at the line 2525 of animations-browser.umd.js, inside the AnimationTransitionNamespace.prototype.trigger function declaration, you will see some comments that shed light on this issue :

// normally this isn’t reached by here, however, if an object expression // is passed in then it may be a new object each time. Comparing the value // is important since that will stay the same despite there being a new object. // The removal arc here is special cased because the same element is triggered // twice in the event that it contains animations on the outer/inner portions // of the host container if (!isRemoval && fromState.value === toState.value) { // this means that despite the value not changing, some inner params // have changed which means that the animation final styles need to be applied`

The file can either be found locally at node_modules/@angular/animations/bundles/animations-browser.umd.js or it is available here : https://github.com/angular/animations-builds/blob/master/bundles/animations-browser.umd.js

This doesn’t fix anything be I hope it will help people encountering this issue have a better understanding of what is going on.

PS: If you look into the minified version of animations-browser.umd.js you can even see that the property “value” is deleted from the object after the check. This means, there is truly no use of it apart from the checking mentioned in the comment.

@matsko I think this can be closed. Here’s an example of a working animation with parameters for anyone who needs it:

It showcases a fill property that accepts a numeric value and animates the width of an element based on that numeric value.

Here’s the open source code that this is drawn from.

animation.ts

import {
    animate,
    state,
    style,
    transition,
    trigger,
    AnimationTriggerMetadata,
  } from '@angular/animations';
  
  export const daffProgressIndicatorAnimation: {
    readonly fill: AnimationTriggerMetadata,
  } = {
    fill: trigger('fill', [
        state('*', style({ width: "{{ percentage }}%"}), { params: { percentage: 0 } }),
        transition('* <=> *', animate(1000))
    ])
  };

indicator.ts

import { Component, Input, ChangeDetectionStrategy, ElementRef, Output, EventEmitter } from '@angular/core';

import { daffProgressIndicatorAnimation } from './animation';
import { AnimationEvent } from '@angular/animations';

@Component({
  selector: 'daff-progress-indicator',
  templateUrl: './progress-indicator.component.html',
  styleUrls: ['./progress-indicator.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: {
    'class': 'daff-progress-indicator'
  },
  animations: [
    daffProgressIndicatorAnimation.fill
  ]
})
export class DaffProgressIndicatorComponent {

  /**
   * The percentage completion of the progression, 
   * expressed as a whole number between 0 and 100.
   * 
   */
  @Input() percentage = 0;

  get fillState(): any {
    return {
      value: this.percentage,
      params: {
        percentage: this.percentage 
      }
    };
  }
}

progress-indicator.component.html

<div class="daff-progress-indicator__fill" [@fill]="fillState"></div>

Try placing a value in the expression (so {value: 'something, params: {}}) (doesn’t matter what it is) and see if it get’s picked up during removal.

@coherent-software Your issue is not about parameters, it is about which state you’re setting the parameters on.

In your original example, you’re only setting params on the “void, hidden” state, but your default visiblity is “visible” so the params never appear to apply.

Here’s a simplified example showcasing this applying by changing the default state: https://stackblitz.com/edit/angular-axk8xe?file=src/app/app.component.ts

I’ve attached a working example with an animation: https://stackblitz.com/edit/angular-1vcmrn?file=src/app/slide.ts

I have the same problem (angular 6.0.2) and opened a post on stackoverflow: https://stackoverflow.com/questions/50806212/how-to-use-input-parameters-in-angular-6-animation

Don’t understand why parameters in Angular Animations are’nt working…

EDIT: It works, I set false values and because of this the animation seems not working.

@matsko

Hi can we expect to see this resolve soon or should we forget about using angular animation when animation has to be customised at runtime to fit application requirements