12/08/2018, 15:41

Animation in Angular 2

Animation is one of the intimidating features that developer have to face. But animation in Angular is easy because Templates are closely associated/integrated with Component and it following a similar pattern. Our goal today is to create an animation of element flying in & out using Angular so ...

Animation is one of the intimidating features that developer have to face. But animation in Angular is easy because Templates are closely associated/integrated with Component and it following a similar pattern. Our goal today is to create an animation of element flying in & out using Angular so lets walk through this together.

Setting Up

First thing we need to do is to import necessary module into our application. Suppose we have our application module setup like below.

import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
  bootstrap: [AppComponent]
})
export class AppModule { }

Then we can enable animation by importing module like this

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  imports: [
    ...,
    BrowserAnimationsModule
  ]
  ...
})
export class AppModule { }

Writing a Component

Lets write a basic alert component that will show or hide text message base on the visible property.

import { Component, Input } from '@angular/core';

@Component({
  selector: 'alert',
  template: `
    <div *ngIf="visible">{{text}}</div>
  `
})
export class AlertComponent {
  @Input('text') text: string = ';
  @Input('visible') visible: boolean = false;
}

@Component({
  template: `
    <div>
      <button (click)="toggleMessage()">Toggle Show</button>
      <alert [text]="message" [visible]="isVisible"></alert>
    </div>
  `
})
export class AppComponent {
  isVisible: boolean;
  message: string;
  
  ngOnInit() {
    this.isVisible = true;
    this.message = 'Hello, do you see me?';
  }
  
  toggleMessage() {
    this.isVisible = !this.isVisible;
  }
}

This is just a simple component that will toggle show or hide the alert message when user click on the button, there is nothing special here. To get the animation lets add the animation rules to AlertComponent.

Apply Animation

@Component decorator also takes an animations property. Any rule that specify in that property will run as part of the animation. So lets go through that together. The example below is saying that before the ngIf kick in and make our element visible, position the element 100% to the left and start moving from there with the duration 300ms to complete and when the element fully visible make it stop at our originally defined position then before the element disappear animate from current position to 100% to the right with the duration 300ms to complete. This create an affect of the element appear flying in from the left and disappear back by flying out to the right.

import { trigger, state, animate, transition, style } from '@angular/animations';

@Component({
  ...,
  template: `
    <div *ngIf="visible" [@flyInOut]="visible">{{text}}</div>
  `,
  animations: [
    trigger('flyInOut', [
      state('in', style({
        transform: 'translateX(0)'
      })),
      transition(':enter', [
        style({
          transform: 'translateX(-100%)'
        }),
        animate(300)
      ]),
      transition(':leave', [
        animate(300, style({
          transform: 'translateX(100%)'
        }))
      ])
    ])
  ]
})
export class AlertComponent {
  ...
}

Kye Take Take Away

Animnation in Angular doesn't necessarily be with directive like ngIf or ngFor, in fact it bases on the component state. For example suppose we have a component that show a list of projects which can let the user toggle between active and inactive status of each project. We can apply animation to express transition between these state by binding the trigger key target name to the status property of the project model like this.

<div [@fade]="project.status"></div>

and in the component metadata we could do something like this

...
animations: [
  trigger('fade', [
    state('inactive', style({ opacity: 0.5 })),
    state('active', style({ opacity: 1.0 })),
    transition('* => *', animate('100ms ease-in'))
  ])
]
...

The * => * in transition mean apply animation with the same duration to both of state change. If you want to make transition from active to inactive to be slower then you can do

...
transition('active => inactive', animate('200ms ease-in')),
transition('inactive => active', animate('100ms ease-in'))
...
0