Angular animation on a single item of an *ngFor list


#1

I am trying to make an animation trigger when a swipe on an item in the list.
In the HTML:

    <ion-list *ngFor="let song of songList | async">
      <ion-item (swipeleft)="vote(song, true); toggleUpvoteAnim()" (swiperight)="vote(song, false)" class="bottom-border" [@myupvote]="upvoteState">
        {{song.title}}
        <div item-right>{{song.upVotes}}</div>
        <div item-right>UP</div>
        <div item-right>|</div>
        <div item-right>DOWN</div>
        <div item-right>{{song.downVotes}}</div>
      </ion-item>
    </ion-list>

In the TS:

@IonicPage()
@Component({
  selector: 'page-guest-song-list',
  templateUrl: 'guest-song-list.html',
  animations: [
    trigger('myupvote', [
      state('noupvote', style({
        backgroundColor: '#191414'
      })),
      state('upvote', style({
        backgroundColor: '#191414'
      })),
      transition('* => *',
        animate('.25s', keyframes([
        style({backgroundColor: '#191414', offset: 0}),
        style({backgroundColor: '#1db954', offset: 0.25}),
        style({backgroundColor: '#191414', offset: 1})
        ]))
      )
    ])
  ]
})
export class GuestSongListPage {

  upvoteState = 'noupvote';
...
}
...
  toggleUpvoteAnim() {
    this.upvoteState = (this.upvoteState == 'upvote') ? 'noupvote ' : 'upvote';
  }

The animation triggers when I swipe, but it applies to the entire list. How can I get it to apply only to the item that was swiped on?


#2

You’re using the same trigger name (myupvote) for every item in the list. So when you change myupvote, it affects every item in the list.

The most “Angulary” way to solve this is to create a Component named song-item, or something along those lines. Define the animation inside the component. Then the scope of the trigger name will be just that item. So the Component displays the item, performs the animation if the item is swiped, and uses an EventEmitter to tell your page, “I was the item swiped.” Your page template then ngFors over song-items, not ion-items.


#3

Thanks for the help! I’m having trouble implementing this. I am a noob so please bear with me. I have managed to create a new component song-item, with song-item.ts containing the animation (including animations in @Component, defining upvoteState, and toggleUpvateAnim), but I can’t get the list to display as intended. The ngFor either creates all the list items, but they are empty and do not contain the information (artist, title, votes), or nothing at all is displayed.


#4

Follow this and make sure you’ve configured the @Input correctly.

https://angular.io/tutorial/toh-pt3


#5

Thank you that helped!