8

I have an expression on a page called 'pointsBalance' that displays numeric value. Its hooked up to an observable, and when pointsBalance value goes up, I want to change the colour to green then back to its original colour, and red if it goes down in value. I thought I could use Angular 5 new animation aliases :increment and :decrement but I've been having problems with it.

HTML to display the points balance:

<div [@valueAnimation]="pointsBalance">{{ pointsBalance }}</div> 

Code that sets the animation and the pointsBalance observable:

import { Component, OnInit, Input } from '@angular/core';
import { trigger, style, transition, animate, keyframes, query, 
    stagger, state, group } from '@angular/animations';
import { CompetitionsService } from "../../../shared/index";
@Component({
  selector: 'points',
  templateUrl: './...html',

  animations: [
    trigger('valueAnimation', [
      transition(':increment', group([
        query(':enter', [
          style({ color: 'green', fontSize: '50px' }),
          animate('0.8s ease-out', style('*'))
        ])
      ])),
      transition(':decrement', group([
        query(':enter', [
          style({ color: 'red', fontSize: '50px' }),
          animate('0.8s ease-out', style('*'))
        ])
      ]))
    ])
  ]
})
export class CompetitionDetailsComponent implements OnInit {

  pointsBalance: number;

  constructor(private competitionsService: CompetitionsService, ) { }

  ngOnInit() {

    this.competitionsService.updatePointsBalance$.subscribe(
      (pointsBalance) => {
        this.pointsBalance = pointsBalance;
      }
    )
  }
}

And when pointsBalance value changes I get this console error:

ERROR Error: Unable to process animations due to the following failed trigger transitions @valueAnimation has failed due to:

  • query(":enter") returned zero elements. (Use query(":enter", { optional: true }) if you wish to allow this.)

Does anyone know why I'm getting this error? Or is there another way to achieve this? Thanks.

3
  • 1
    The error message actually offers a workaround (which is nice). Did you give that a try? Commented Apr 8, 2018 at 14:19
  • Yes I did - but the animation still didn't work. Commented Apr 8, 2018 at 15:47
  • I mean I added { optional: true } and it still didn't work Commented Apr 8, 2018 at 15:53

3 Answers 3

3

the :enter animation will only animate elements that are newly created. Your "hacky" workaround works because it forces the inner span to get recreated whenever the value changes. I think what you want is to remove the :enter query. You want to animate when the number is in/decremented, and your animation has nothing to do with elements being added.

Sign up to request clarification or add additional context in comments.

2 Comments

Hey Benjamin. Many thanks for your explanation. You are right, I want to animate as the number is in/decremented. Do you know how I can achieve this?
I think you just need to remove the enter query so it doesn't "filter" the animation to only apply to entering elements
2

I found a fix from here and here.

<div [@valueAnimation]="pointsBalance"><span *ngFor="let pointsBalance of [ pointsBalance ]">{{ pointsBalance }}</span></div>

Feels a bit hacky though.

Comments

2

I'm just going to paste the code as it would look, as Benjamin Kindle said, I tried it and it worked:

animations: [
    trigger('valueAnimation', [
      transition(':increment', [
          style({ color: 'green', fontSize: '50px' }),
          animate('0.8s ease-out', style('*'))
        ]
      ),
      transition(':decrement', [
          style({ color: 'red', fontSize: '50px' }),
          animate('0.8s ease-out', style('*'))
        ]
      )
    ])
  ]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.