Tutorial hero
Lesson icon

Animating from the Void: Enter and Exit Animations in Ionic

Originally published September 07, 2017 Time 8 mins

Last week I wrote a tutorial that covered how to create a simple add to cart animation using the Angular animations library (which is based on the Web Animations API).

To quickly recap, creating animations with the Angular animations library involves creating “triggers” with “states” that define a set of styles and then defining “transitions” between those states. The state is associated with a trigger attached to an element, like this:

<my-element [@myTriggerState]="something"></my-element>

A state can be any string value that we define. We might use values like active and inactive or idle or inprogress and so on. We then define transitions by using matchers like this:

(active) => inactive;

or

inactive => *

Using this method, we can easily target the specific state transition that we want to target. This is a problem when trying to create entry and exit animations for elements – perhaps we want an item in a list to fly in from the left when it is added. We can’t associate a state with something that doesn’t exist yet.

In this tutorial, we will be discussing how we can use the special void state to create entry and exit animations. We will be creating an animation that will cause items to fly in from the left, and when they are deleted they will fly out to the right:

Void Animation in Ionic

If you do not already have a basic understanding of creating animations with the Angular animations library, I would recommend reading the previous tutorials first.

Before We Get Started

Last updated for Ionic 3.6.0

Before you go through this tutorial, you should have at least a basic understanding of Ionic concepts. You must also already have Ionic set up on your machine.

If you’re not familiar with Ionic already, I’d recommend reading my Ionic Beginners Guide or watching my beginners series first to get up and running and understand the basic concepts. If you want a much more detailed guide for learning Ionic, then take a look at Building Mobile Apps with Ionic.

Setting up Angular Animations

There are a few dependencies that need to be installed in order to be able to use the Angular animations library in your application. For details on how to set that up in an Ionic application, please take a look at the previous tutorial.

The Void State

To understand how to create enter and exit animations for elements, we need to understand a special state called void.

The void state is the state that an element will be in when it does not exist in the DOM. If you wanted to create an animation that applies when a particular element is added to the application, you couldn’t define the appropriate state transition because it doesn’t exist yet and so it has no associated state. Using the special void state allows us to create enter and exit animations.

The void state is a bit awkward because you might want to define some styles for the void state like this:

trigger('itemState', [
  state(
    'void',
    style({
      transform: 'translateX(-100%)',
    })
  ),
  transition('void => *', animate('500ms ease-out')),
]);

This is basically saying that when an element that this trigger is associated with is in the void state it should be moved 100% to the left of its current position (e.g. off the screen to the left). Then we have a transition for void => * so that the animation will apply as soon as the element is added to the application (since it will no longer have the void state).

This is fine, and it will work, but consider that if we have this void animation that will cause the element to come into the screen from the left, what if we wanted that element to fly off to the right of the screen when it is removed? When the element is removed it will be given the void state again, but the style we have defined for the void state moves the element off to the left of the screen, not the right. We need different styles to apply depending on whether the element is being added:

void => *

or the element is being removed:

* => void

Although we can create states with specific styles, we can also define style directly on transitions as well. This means that we could do this:

trigger('itemState', [
  transition('void => *', [
    style({ transform: 'translateX(-100%)' }),
    animate('500ms ease-out'),
  ]),
  transition('* => void', [
    animate('500ms ease-in', style({ transform: 'translateX(100%)' })),
  ]),
]);

This defines both an enter and a leave animation. For the void => * transition, which is the enter transition, we add a style that moves the element off to the left of the screen. The exit transition, which is * => void, looks slightly different. We have styling that will move the element off to the right of the screen, but we add the style inside of the animate method. This is because we don’t want the element to have that style at the beginning of the transition, we want to animate to that style from whatever styles it currently has.

Creating the Animation

We are going to use that void state now to finish implementing the animation we have been discussing.

Add the following animation to the @Component metadata:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { trigger, state, style, animate, transition } from '@angular/animations';

@Component({
    selector: 'page-home',
    templateUrl: 'home.html',
    animations: [
        trigger('itemState', [
            transition('void => *', [
                style({transform: 'translateX(-100%)'}),
                animate('500ms ease-out')
            ]),
            transition('* => void', [
                animate('500ms ease-in', style({transform: 'translateX(100%)'}))
            ])
        ])
    ]
})
export class HomePage {

    items: string[] = [];

    constructor(public navCtrl: NavController) {

    }

    addItem(){
        this.items.push('test');
    }

    deleteItem(item){
        this.items.splice(this.items.indexOf(item), 1);
    }

}

We have created two transitions inside of the itemState trigger. The first handles the case for an element being added to the DOM, from “the void” to any state. We apply a style that will transform its position off to the left side of the screen, and we define how we want the animation to run. The second transition, from any state to “the void”, defines the styles inside of the animate method because we want to animate to that style.

I’ve also included some test code that you can use to handle adding items to an array and deleting them.

Adding the Animation to List Items

Now that we have our trigger defined, we just need to associate it with the list items:

Attach the trigger to an element

<ion-header>
  <ion-navbar color="primary">
    <ion-title> Void Animations </ion-title>
    <ion-buttons end>
      <button ion-button icon-only (click)="addItem()">
        <ion-icon name="add"></ion-icon>
      </button>
    </ion-buttons>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <ion-list no-lines>
    <ion-item @itemState (click)="deleteItem(item)" *ngFor="let item of items">
      Cold is the void...
    </ion-item>
  </ion-list>
</ion-content>

Since we are only creating enter and exit animations, there is no need to associate the trigger with a state, so we don’t need to set up a property binding like we usually would, i.e:

<ion-item
  [@itemState]="someVar"
  (click)="deleteItem(item)"
  *ngFor="let item of items"
></ion-item>

I’ve also included the rest of the test code so that you can click the button in the navbar to add new items (and clicking any item will also trigger a delete). If you were to give this a test now, you should have something like this:

Void Animation in Ionic

Summary

The Angular animations syntax can be a bit to get your head around at first, but once you understand how to use the void state it is a very simple way to create entry and exit animations in your Ionic applications.

Learn to build modern Angular apps with my course