5

Need to trigger animation every time the array changes

I am currently iterating over an array of products using *ngfor and everytime the length changes the animation will trigger. I am using Angular 4.

<ul class="items col col-md-12" *ngIf="hasProducts()" [@productsIntro]="products.length">

The issue is that I need the animation to trigger everytime the array changes at all and not just the length of the array. Sometimes the array length will be the same but the items in the array are different so the animation will not trigger.

I am not sure on how to pull this off and was hoping someone could help me out with a solution.

<ul class="items col col-md-12" *ngIf="hasProducts()" [@productsIntro]="products.length">
    <li class="col col-xs-12 col-sm-12 col-md-4" *ngFor="let product of products">
      <div class="item">
        <a href="" class="product-name">{{product.product_name}}</a>
        <div class="image-and-info col col-xs-8 col-sm-8 col-md-12">
          <div class="product-thumb">
            <img src="../../assets/img-filler.png" alt="{{product.product_name}}">
          </div>
          <div class="info">
            <div class="sku">SKU: {{product.sku}}</div>
            <div class="price">Price: {{product.price | currency:'USD':true:'1.2-2'}}</div>
          </div>
        </div>
        <div class="product-col col col-xs-4 col-sm-4 col-md-12">
          <div class="btn-group" role="group" aria-label="Basic example">
            <button type="button" class="btn btn-solid" (click)="viewProduct(product)">View Product</button>
            <button type="button" class="btn btn-solid add-to-cart" (click)="addToCart($event)">Add to Cart</button>
          </div>
        </div>
      </div>
    </li>
  </ul>

trigger form component:

trigger('productsIntro', [
  transition('* => *', [
    query(':enter', style({ opacity: 0 }), {optional: true}),
    query(':enter', stagger('100ms', [
      animate('1s ease-in', keyframes([
        style({opacity: 0, transform: 'translateY(-10%)', offset: 0}),
        style({opacity: .5, transform: 'translateY(10px)',  offset: 0.3}),
        style({opacity: 1, transform: 'translateY(0)',     offset: 1.0}),
      ]))]), {optional: true})
  ])
])
Travis Michael Heller
  • 1,210
  • 3
  • 16
  • 34
  • "the items in the array are different" : What are the changes on the items ? What makes them change ? – br.julien Nov 07 '17 at 19:11
  • products are added and removed based on what category buttons the user clicks on. so every time the user clicks on a new category button the products array will change. – Travis Michael Heller Nov 07 '17 at 19:17
  • I think if you use states, you could trigger the animation both when products.length changes and when you click anywhere to make changes on the items – br.julien Nov 07 '17 at 19:28
  • I read into the states and still a little confused on how to implement into my code. Looking at the Angular docs for animations I see they are using [@heroState]="hero.state" but I am not sure where the hero.state is referring to. I am still new to Angular so please excuse me if I am missing the obvious. – Travis Michael Heller Nov 07 '17 at 19:38
  • Currently, i having my animations switching every time the array changes but it does not work the first time I show the products on the list. Ended up doing [@productsIntro]="animationState" on HTML component. and using a toggle function every time I change the array to change the value of animationState. It should work the first time I load the array but it doesn't which is confusing. – Travis Michael Heller Nov 07 '17 at 19:42
  • Every time my array has a length of 0 and then the length changes the animation does not work. – Travis Michael Heller Nov 07 '17 at 19:49
  • Can you make a StackBlitz example of your animation please , It would be easier to help. – br.julien Nov 07 '17 at 19:51
  • Thanks for taking the time to help me out @Brice. – Travis Michael Heller Nov 07 '17 at 19:54

1 Answers1

4

Found out the animation was not being triggered when the products array length starts from 0 and then changes. My solution was to remove a conditional in the HTML component and add toggle function to change variable state everytime the array was changed:

Toggle Function:

animationState = 'inactive';
toggleState() {
this.animationState = this.animationState === 'active' ? 'inactive' : 'active';

}

changed from:

<ul class="items col col-md-12" *ngIf="hasProducts()" [@productsIntro]="animationState">
    <li class="col col-xs-12 col-sm-12 col-md-4" *ngFor="let product of products">

changed to:

<ul class="items col col-md-12"  [@productsIntro]="animationState">
    <li class="col col-xs-12 col-sm-12 col-md-4" *ngFor="let product of products">
Travis Michael Heller
  • 1,210
  • 3
  • 16
  • 34
  • Thank you for your solution, Can you make a StackBlitz example and let us know how you trigger toggle method – Ganesh Jangam Aug 13 '19 at 09:19
  • solution works fine, but previously rendered element still show with animation on screen after newly rendered array and take more time than actual to call done method, please help – Ganesh Jangam Aug 13 '19 at 10:14