List animation in Ionic 6 & Angular
Tags: ionic, angular, opensource, tutorial
Published: 2022-02-11 07:48:04

In this article we're gonna learn how to create list animations in Ionic.

We're gonna implement this animation

![List animation ionic gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/39s19b48n0abbjx2hrul.gif)

## Create Grid List
First we need to implement a Grid List of 2 columns, that we can implement using below code

**home.page.html**
```html
<ion-content>
  <ion-grid>
    <ion-row>
      <ion-col
        size="6"
        *ngFor="let temp of templates;"
      >
        <ion-item
          class="ion-no-padding"
          lines="none"
        >
          <ion-img [src]="temp.background"> </ion-img>
        </ion-item>
      </ion-col>
    </ion-row>
  </ion-grid>
</ion-content>
```

It's a simple code, here `size="6"` gives every item half of screen width, as explained in [ion-grid](https://ionicframework.com/docs/api/grid) documentation 

> It (grid) is based on a 12 column layout with different breakpoints based on the screen size

And `templates` here is list array we have defined in **home.page.ts** 

```Typescript
export class HomePage implements AfterViewInit {
  // You can give your own background asset path here
  templates = [
    {
      id: 0,
      background: 'assets/hotel/hotel_booking.png',
      screenPath: 'hotel-booking',
    },
    {
      id: 1,
      background: 'assets/fitness_app/fitness_app.png',
      screenPath: 'fitness-app',
    },
    {
      id: 2,
      background: 'assets/design_course/design_course.png',
      screenPath: 'design-course',
    },
  ];

  constructor() {}
}
```

## Implement the Animation
Now we need to implement the animation, for that we need reference for list items

- First assign id to `ion-col` which will contain reference 
  for all child items

**home.page.html**
```html
<ion-content>
  <ion-grid>
    <ion-row>
      <ion-col
        size="6"
        *ngFor="let temp of templates;"
        #templateList   <- Add this
      >
        // same as above
      </ion-col>
    </ion-row>
  </ion-grid>
</ion-content>
```

- Now in **home.page.ts** we're gonna use [ViewChildren] 
  (https://angular.io/api/core/ViewChildren) as we need 
  reference for every list item to animate

```Typescript
export class HomePage implements AfterViewInit {
  // Here 'templateList' is the id
  @ViewChildren('templateList', { read: ElementRef })
  templateListRef: QueryList<ElementRef>;

  ...
}
```

- Now next step is to animate list items using reference 
  variable `templateListRef` we created in last step


```Typescript
import { AnimationController } from '@ionic/angular';

export class HomePage implements AfterViewInit {
  @ViewChildren('templateList', { read: ElementRef })
  templateListRef: QueryList<ElementRef>;

  constructor(private animationCtrl: AnimationController) {}

  ngAfterViewInit() {
    this.initListAnimation();
  }

  initListAnimation() {
    const itemRefArray = this.templateListRef.toArray();
    for (let i = 0; i < itemRefArray.length; i++) {
      const element = itemRefArray[i].nativeElement;

      this.animationCtrl
        .create()
        .addElement(element)
        .duration(1000)
        .delay(i * (1000 / 3))
        .easing('cubic-bezier(0.4, 0.0, 0.2, 1.0)')
        .fromTo('transform', 'translateY(50px)', 'translateY(0px)')
        .fromTo('opacity', '0', '1')
        .play();
    }
  }
}
```
Here as we need to wait for screen to first initialise only then we can get reference for any view, we will run our animation in `ngAfterViewInit`.
In `initListAnimation` function we're iterating over `templateListRef` as we need to animate every item in the list
You can read the Ionic Animation documentation [here](https://ionicframework.com/docs/utilities/animations) to get an idea how animations works in ionic.

1. First we need to import `AnimationController` through which we can animate any element, then defined it in constructor.
2. `addElement(element)`:- Add element that we're animating, here element is list item.
3. `duration(1000)`:- animation will run in 1000ms (1 second) duration.
4. `delay(i * (1000 / 3))`:- Animation for subsequent items will be delayed so that all items don't animate at the same time but one after the other.
5. `easing`:- Easing effect for animation, visit [here](https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function) for better understanding.
6. `fromTo` basically animate a element's properly from start to end position. Like here as you can see in the gif above items are translating vertically and slowly fading in, so here we are animating `transform` from initial 50px below to 0px and `opacity` from 0 to 1.
7. `play`:- Play the animation with all specified properties.

_And it's done, the list animation should work as expected._


## Flicker issue with android
Don't know about you but for me on android the list was flickering a little as shown in gif below

![List flicker android issue](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9cqx6aohh72iskpxnk6.gif)
 
Now if you search for this issue on google you'll most probably find suggestion to use [trackBy](https://angular.io/api/core/TrackByFunction) as [here](https://github.com/ionic-team/ionic-framework/issues/17342#issuecomment-459639340) and [here](https://stackoverflow.com/a/60202913) where we give every list item a unique id, but for some reason it didn't fix it for me.
So I had to come up with below workaround.
Here we wait for 500ms for page to initialise properly, the run the animation.

**home.page.ts**
```Typescript
export class HomePage implements AfterViewInit {
  constructor(
    private animationCtrl: AnimationController,
    private platform: Platform // <- add this
  ) {}

  ngAfterViewInit() {
    // move 'initListAnimation' function inside timeout
    // As I faced this issue only on Android, we won't wait in case of iOS
    setTimeout(
      () => this.initListAnimation(),
      this.platform.is('android') ? 500 : 0
    );
  }
}
```

In **home.page.html** we'll give initial `opacity: 0` as list items shouldn't show to user while we're waiting (500ms)
```html
<ion-content>
  <ion-grid>
    <ion-row>
      <ion-col
        style="opacity: 0"   <- Add this
        size="6"
        *ngFor="let temp of templates;"
        #templateList
      >
        // same as above
      </ion-col>
    </ion-row>
  </ion-grid>
</ion-content>
```

This should fix the issue.
**Do suggest if there's a better solution.**

## Conclusion
Following the above steps animation should work as expected.
This article is part of my open source project [Ionic-UI-Templates](https://github.com/Aashu-Dubey/Ionic-UI-Templates), so do check that out for complete code. In this project I'm using Ionic 6 with Angular and Capacitor as runtime environment.

Repo link:- [Ionic-UI-Templates](https://github.com/Aashu-Dubey/Ionic-UI-Templates)

Video:- {% embed https://www.youtube.com/watch?v=9ssPXzVecas %}


**Note:-** This is my first ever article in any platform, so I would really appreciate for any suggestions to improve the article. Also there could be lot of grammatical mistakes so try to ignore them or do provide correction in the comments below, Thanks.