Goutam B Seervi
Goutam B Seervi

Reputation: 1226

Angular Animation being triggered only once

I have a application which displays random quotes every 30seconds. I wanted to use angular animations to animate those quotes. The problem that I am facing is that the text is animated only first (when the page is first loaded). But instead it should animate every time quote changes.

Here's the code I've already tried

import {Component, OnInit} from '@angular/core';
import {QuoteService} from '../services/quote.service';
import {animate, state, style, transition, trigger} from '@angular/animations';

@Component({
  selector: 'app-quote-item',
  templateUrl: './quote-item.component.html',
  styleUrls: ['./quote-item.component.css'],
  animations: [
    trigger('changeQuote', [
      state('true', style({
        opacity: '1'
      })),
      state('false', style({
        opacity: '0'
      })),
      transition('0 <=> 1', animate('1000ms ease'))
    ])
  ]
})
export class QuoteItemComponent implements OnInit {
  changeQuote = true;
  quote = {};

  constructor(private service: QuoteService) { }

  ngOnInit() {
    this.getQuote();
    setInterval(this.getQuote, 30000);
  }

  getQuote = () => {
    this.changeQuote = false;
    this.service.getRandomQuote().subscribe( quote => {
      this.quote = quote;
      this.changeQuote = true;
    });
  }
}

The HTML Code:

<div [@changeQuote]="changeQuote" class="container">
  <div class="row">
    <div class="col quote my-auto">
      <div class="text-center">
        <p class="text" [innerText]="quote['quote']"></p>
      </div>
      <div class="text-right" style="margin-right: 25px">
        <p style="font-weight: bold; font-size: 38px;" [innerText]="quote['author']"></p>
      </div>
    </div>
  </div>
</div>

Upvotes: 1

Views: 2642

Answers (2)

Jonathan Stellwag
Jonathan Stellwag

Reputation: 4287

Here is a working example for your animation: quote-animation This example only uses your setInterval to change the state of your animation.

The main problem is your subscription inside getQuote():

  1. Every time you call getQuote() you open a new subscription. (Or is your Observable completed after 1 emit).
  2. Therefore a subscription is not called when your setInterval triggers the function -> It is called whenever your service results a getRandomQuote()
  3. Also we do not know how your getRandomQuote() looks like. This is all a conjecture.

Upvotes: 1

julianobrasil
julianobrasil

Reputation: 9377

The problem is that @angular's change detection is not capturing the switch from true => false => true (the changes are made before the change detector has a chance to do anything). If you put a delay on your service subscription, you'll see the animation:

getQuote = () => {
  this.service.getRandomQuote().pipe(
  tap(_ => this.changeQuote = false),
  delay(1000)).subscribe(quote => {
    this.quote = quote;
    this.changeQuote = true;
  });
}

See this demo: Stackblitz

Upvotes: 0

Related Questions