Tutorial built with Angular 5.0.3

Other versions available:

In this tutorial I'll show you how you can implement animations between routes in Angular 2/5 and TypeScript.

Project code is available on GitHub at https://github.com/cornflourblue/angular2-animation-tutorial-example.



Difference Between Angular 2/5 Animations and AngularJS Animations

Animations in Angular 2/5 work completely differently to Angular 1, in Angular 1 there are css class hooks that you can use to animate elements into view and out of view, whereas in Angular 2/5 animations are implemented inside your components using a set of functions (trigger, state, animate, transition, style) from the new '@angular/animations' package.

Animation styles are still defined using CSS but they're written in TypeScript using JSON objects (TSON?) instead of CSS/LESS files, there's also a new Angular Animation DSL (Domain Specific Language) that has been created to define different states and transitions between states. I won't go too much into the details of all the new bits and pieces of the animation system since you can find all that information on the angular docs site, instead I'll focus on an example and how to get animations working between routes.

Don't feel bad if the new angular animation system has had you banging your head against the wall in frustration, it's taken me an embarrassingly long time to get my head around and I'm still coming to grips with it!



Angular 2/5 Animations Tutorial Demo

Here's the tutorial example application in action, it uses a fade transition between top level tabs and a slide in/out transition on the products page for adding and editing a product.

(See on Plunker at https://plnkr.co/edit/AfIB1i?p=preview)



Running the Angular 2/5 Animation Tutorial Demo Locally

Install NodeJS and NPM from https://nodejs.org/en/download/, you can check the versions you have installed by running node -v and npm -v from the command line.

Download the project source code from https://github.com/cornflourblue/angular2-animation-tutorial-example

Install all required npm packages by running npm install from the command line in the project root folder (where the package.json is located).

Start the application by running npm start from the command line in the project root folder.



Let's stay focused on the animations

I tried to make the example a real world-ish application so it contains a few services and other bits and pieces but I'm just going to focus on the animations in this post and how to add them to your Angular 2/5 routes.



Import BrowserAnimationsModule into app.module.ts

With the release of Angular 4, animations were split out from the angular core into their own module, so to use animations you have to import the BrowserAnimationsModule at the top of your app.module.ts file:

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



And add the BrowserAnimationsModule to the list of imports in your @NgModule metadata:

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



The first import makes BrowserAnimationsModule available to code inside the app.module.ts file, and the second import makes all the public functions from BrowserAnimationsModule available to other components in AppModule .



Define Your Angular 2/5 Animations

Animations can be defined directly inside your components but I prefer to separate them into their own files, this allows you to re-use the animations anywhere in your application and makes component code much cleaner as it maintains a good separation of concerns.

In the example I've put animations in the app/_animations folder, I like to prefix non-feature folders with an underscore '_' to group them together at the top and separate them from feature folders. Feature folders contain code for views / routes in your application such as home and products, non-feature folders contain shared code such as services, animations, directives, css etc, basically everything else.



Angular 2/5 Fade In Animation

The fade in animation that's used by the home component and product list component in the example.

// import the required animation functions from the angular animations module import { trigger, state, animate, transition, style } from '@angular/animations'; export const fadeInAnimation = // trigger name for attaching this animation to an element using the [@triggerName] syntax trigger('fadeInAnimation', [ // route 'enter' transition transition(':enter', [ // css styles at start of transition style({ opacity: 0 }), // animation and styles at end of transition animate('.3s', style({ opacity: 1 })) ]), ]);



Angular 2/5 Slide In/Out Animation

The slide in/out animation that's used by the product add/edit component in the example.

// import the required animation functions from the angular animations module import { trigger, state, animate, transition, style } from '@angular/animations'; export const slideInOutAnimation = // trigger name for attaching this animation to an element using the [@triggerName] syntax trigger('slideInOutAnimation', [ // end state styles for route container (host) state('*', style({ // the view covers the whole screen with a semi tranparent background position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0, 0, 0, 0.8)' })), // route 'enter' transition transition(':enter', [ // styles at start of transition style({ // start with the content positioned off the right of the screen, // -400% is required instead of -100% because the negative position adds to the width of the element right: '-400%', // start with background opacity set to 0 (invisible) backgroundColor: 'rgba(0, 0, 0, 0)' }), // animation and styles at end of transition animate('.5s ease-in-out', style({ // transition the right position to 0 which slides the content into view right: 0, // transition the background opacity to 0.8 to fade it in backgroundColor: 'rgba(0, 0, 0, 0.8)' })) ]), // route 'leave' transition transition(':leave', [ // animation and styles at end of transition animate('.5s ease-in-out', style({ // transition the right position to -400% which slides the content out of view right: '-400%', // transition the background opacity to 0 to fade it out backgroundColor: 'rgba(0, 0, 0, 0)' })) ]) ]);



Attach the Angular Animations to Your Routed Components

With the animations cleanly separated into their own files it's easy to attach them to your angular routes, all you need to do is import the animation you want to use and add it to your @Component metadata.



Angular 2/5 Home Component with Fade In Animation

The home component from the example with the fade in animation attached.

import { Component } from '@angular/core'; // import fade in animation import { fadeInAnimation } from '../_animations/index'; @Component({ moduleId: module.id.toString(), templateUrl: 'home.component.html', // make fade in animation available to this component animations: [fadeInAnimation], // attach the fade in animation to the host (root) element of this component host: { '[@fadeInAnimation]': '' } }) export class HomeComponent { }



Angular 2/5 Product List Component with Fade In Animation

The product list component from the example with the fade in animation attached.

import { Component, OnInit, OnDestroy } from '@angular/core'; import { Subscription } from 'rxjs/Subscription'; import { ProductService, PubSubService } from '../_services/index'; // import fade in animation import { fadeInAnimation } from '../_animations/index'; @Component({ moduleId: module.id.toString(), templateUrl: 'product-list.component.html', // make fade in animation available to this component animations: [fadeInAnimation], // attach the fade in animation to the host (root) element of this component host: { '[@fadeInAnimation]': '' } }) export class ProductListComponent implements OnInit, OnDestroy { products: any[]; subscription: Subscription; constructor( private productService: ProductService, private pubSubService: PubSubService) { } deleteProduct(id: number) { this.productService.delete(id); this.loadProducts(); } ngOnInit() { this.loadProducts(); // reload products when updated this.subscription = this.pubSubService.on('products-updated').subscribe(() => this.loadProducts()); } ngOnDestroy() { // unsubscribe to ensure no memory leaks this.subscription.unsubscribe(); } private loadProducts() { this.products = this.productService.getAll(); } }



Angular 2/5 Product Add/Edit Component with Slide In/Out Animation

The product add/edit component from the example with the slide in/out animation attached.