Animations are getting more common in a lot of modern applications. So here, we’ll learn how to add animations to our Angular apps. By the end of this article, you’ll have a good understanding of,
- the structure of the animations
- ways of animating various elements in the DOM
- how to create reusable animations
- how to use the new animation functions in Angular 4.3
- how to write clean and maintainable animation code
If you’re an absolute beginner with Angular, then you can start your journey from here.
- Introduction And Setting Up The Environment - Part One
- Typescript in a Nutshell - Part Two
- Building Blocks of Angular - Part Three
- Binding Variations And Displaying Data - Part Four
- Building Reusable Components – Part Five
- Directives – Part Six
- Template Driven Forms – Part Seven
- Reactive Forms – Part Eight
- CRUD Application with Fake HTTP Service – Part Nine
- Handling Errors in Angular – Part Ten
- Routing and Navigation – Part Eleven
- Authentication and Authorization – Part Twelve
- Preparing the Angular Apps For Deployment – Part Thirteen
Let’s get started.
Different Ways to Create the Animations
There are 2 primary ways to create the animation in the Web application. We can use CSS and Javascript to create the animations. In CSS, we have a couple of properties like transition and animation. And with these properties, we can animate DOM elements. Here is an example; let’s suppose we’ve defined the class in CSS.
- .stretch {
- animation-name: stretch;
- animation-duration: 1.5s;
- }
Now when we apply this class to a DOM element, the browser will animate that element. And if we have been working with CSS for a while, you might have heard about the library animate.css. This is the library that gives us a bunch of predefined classes for various kinds of animations. So, we don’t need to manually build the animations with CSS properties. Take a look at the GitHub page of this library. We integrate it in the project via npm. We need to import it in the styles.css just like how we imported bootstrap into our styles.css in our previous articles. And then, start working with animate.css classes.
So as you saw, we can certainly use CSS to add animations but this CSS animation gives us limited control. We often use this with simple, one-shot animations like showing a tooltip or toggling UI elements. If you want to build something more complex, then you really need to use JavaScript. In terms of implementation, there are various libraries out there that give you an API for implementing animations in JavaScript. For example,
- jQuery
- GSAP
- Zepto
- Web Animations API
The recommended approach is to use Web Animations API which is basically a specification of animating DOM elements and is currently supported natively with Chrome, Firefox, and Opera. So, if you head over to caniuse.com, here you can see what features are implemented in what browsers. Here, you can see Web Animations are supported in what browsers. Microsoft IE and Edge are behind in the game just like but don’t worry, because there are polyfills that you can install and then you can use Web Animation in these other browsers too. We get the HTML element with querySelector and apply the animate() method on that element.
Angular Animations
Now let’s see how to build the animations in our angular apps. So as we know we have a module called @angular/animation. In this module, we have a bunch of helper functions for creating animations such as trigger(), transition(), state(), animate() and so on. Before we explore these functions in details, let’s take a look at the anatomy of an animation. Look at this illustration.

What you see here is the concept behind every animation whether you’re a programmer or an animator, you’re dealing with the same concept. The concept is the DOM element can be in any given state (State1), in this state we have a certain look and feel perhaps its background is blue. Now during the animation, it transitions to a different state and in this state it has a different look. Perhaps its background is yellow. This is the anatomy of every animation. We have various states, in each state our element has a different look and during an animation it transitions to one state to another. Now what are these states? In Angular we have 3 kinds of states.
- Void State
It is not part of the DOM and this can happen when an element is created but now placed in the DOM yet or when it removes from the DOM.
Here we have a real world example. Think of a Todo list, every time we add an item in the list the corresponding element is first created but is not in the DOM yet. So it is in the void state. And then it transition from this state to a new state. Similarly when we delete the item from the list, the corresponding element transitions from its current state into the void state. So here * represents to what we call the Default state.
So all elements do have a default state.
- Default State
- Custom State
We always use custom states because they only make sense in certain scenarios. For example, think of a zippy or an accordion component. This component is always visible in the view but it state can change from collapse to expanded. So if we want to implement an animation during this transition then will have to work with 2 custom states here (collapse and expanded)
Now let’s see the implementation, let’s say we want to apply the animation to each item in a list. We start with the component metadata, here we have a property called animation which takes an array. In this array, we register one or more triggers. Each trigger has a name and we add its implementation, we define all the states and transitions to that kind of animation. So this function you see here like trigger(), state() and transition() these are the helper functions that are defined in @angular/animations module.
- @Component({
- animations: [
- trigger('fadeIn', [
- state(...)
- transition(...)
- ])
- ]
- })
You will see this in action. So here we have a trigger called fadeIn. Now we can apply this trigger to any DOM element using this notation
- <div @fadeIn></div>
So this is the big picture.
Importing the Animations Module and Polyfills
So we’re ready to implement the first animation. And if you want to code along with me I have attached the ‘animations-demo’ file with article. So run the command,
- PS C:\Users\Ami Jan\animations-demo\animations-demo> npm install
- PS C:\Users\Ami Jan\animations-demo\animations-demo> ng serve
So in this application we have simple todo list. We can add a new item and we can delete existing item by clicking it. Currently we don’t have any animation here. So
Step 1
Let’s import the animations module in the app module. So let’s go to the app.module.ts
- import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
- import { BrowserModule } from '@angular/platform-browser';
- imports: [
- BrowserModule,
- BrowserAnimationsModule
- ]
So this BrowserAnimationsModule includes all the code for running animations in a browser. As I told you before this BrowserAnimationsModule is implemented on top of the standard Web Animations API and this api is natively supported in firefox, chrome and opera. So to support the other browsers, we need to add polyfills.
Polyfills
It is basically the code that allows you to use modern javascript features in old browsers.
Step 2
So back in the src folder, we can see we have polyfills.ts. Open polyfills.ts, here on line 40 and 41 we have a commented line for importing Web Animations polyfill. Uncomment this line
- /** IE10 and IE11 requires the following to support `@angular/animation`. */
- import 'web-animations-js'; // Run `npm install --save web-animations-js`.
And now here we need to manually install this node module ‘web-animations-js’
PS C:\Users\Ami Jan\animations-demo\animations-demo> npm install --save web-animations-js
So this is how we add animations support to an existing application.
Implementing a Fade In Animation
Alright let’s go to the our todos.component.ts. So here we have a basic todos component. Now in the component metadata, we add a new property called ‘animations’ and we define the array and in this array we define one or more triggers.
- @Component({
- // tslint:disable-next-line:component-selector
- selector: 'todos',
- templateUrl: './todos.component.html',
- styleUrls: ['./todos.component.css'],
- animations: [
- trigger('fade', [
- ])
- ]
- })
And here we give the name to the trigger() function and then as a second argument we need to pass an array. In this array, we register all the states and the transitions to implement this animation.
Before going any further, let’s go to template and apply this trigger. So, todos.component.html
- <div *ngIf="items" class="list-group" >
- <button type="button"
- @fade
- *ngFor="let item of items"
- (click)="removeItem(item)"
- class="list-group-item"
- >{{ item }}</button>
- </div>
This is where we render all the todo item. Each todo item is a button and here you can see we have applied ngFor directive. And this is where we apply the name of the trigger. And if you don’t do this, you’re not gonna see the animation. So back in the component, now here in trigger() function array we need to register all the states and the transitions of this animation. So we often have calls the 2 functions (state(), transition()) and both these functions are defined in @angular/animations
- @Component({
- // tslint:disable-next-line:component-selector
- selector: 'todos',
- templateUrl: './todos.component.html',
- styleUrls: ['./todos.component.css'],
- animations: [
- trigger('fade', [
- state(),
- transition()
- ])
- ]
- })
It is easy to start with transition() function and this function needs 2 arguments. First argument is the string and called statechange expression. With this expression we define source (target state)
- @Component({
- // tslint:disable-next-line:component-selector
- selector: 'todos',
- templateUrl: './todos.component.html',
- styleUrls: ['./todos.component.css'],
- animations: [
- trigger('fade', [
- transition('void => *')
- ])
- ]
- })
That means when our element goes from the void state to the default state then we define the array and in this array we define the steps that should run during this animation. So in order to implement fadeIn effect, we want to apply certain styles during transition when the element is treated but is not placed in the DOM yet. In this array we often have called the 2 functions (style() and animate()). Style() function contains an object containing the key-value pairs where keys are CSS properties. So if we want to change the background color of this element during this transition.
- import { Component } from '@angular/core';
- import { trigger, transition, style, animate } from '@angular/animations';
- @Component({
- // tslint:disable-next-line:component-selector
- selector: 'todos',
- templateUrl: './todos.component.html',
- styleUrls: ['./todos.component.css'],
- animations: [
- trigger('fade', [
- transition('void => *', [
- style({ backgroundColor: 'yellow', opacity: 0 }),
- animate()
- ])
- ])
- ]
- })
So this style function will apply these styles here immediately during this transition. And one more thing, all these triggers and functions which we are using to apply the animation belong to @angular/animations. Before Angular 4, they belonged to @angular/core. So if auto-import plugin adds these functions into @angular/core module in header reference, make the correction your own. animate() function is also similar and it takes 2 arguments. First argument is the timing and the 2nd argument is the style object
- animations: [
- trigger('fade', [
- transition('void => *', [
- style({ backgroundColor: 'yellow', opacity: 0 }),
- animate(2000, style({ backgroundColor: 'white', opacity: 1 }))
- ])
- ])
- ]
So this animate function will apply these styles over this given period of time which is 2000ms and 2s. This is the only difference between style() and animate() function. The style() function applies the style immediately but the animate() function applies them over a period of time. So when you run this code, the background color of our element is going to be initially yellow and then over 2s it will gradually change to white. And opacity will be initially 0 and then it will change to 1. Now open the browser and watch the results, when you refresh the page. The items initially had the yellow background and then it will gradually changes to white background over 2s.
Now back to our component, and let’s make code little bit cleaner. So let’s say remove the 2nd argument of animate(), we don’t explicitly need to change the background color to white and opacity change to 1 because Angular is smart enough to know that in the target state which is the default(*) state
- transition('void => *',
Our item should have the white background and the opacity should be 1. So we don’t need to explicitly specify them here. So,
- animations: [
- trigger('fade', [
- transition('void => *', [
- style({ backgroundColor: 'yellow', opacity: 0 }),
- animate(2000)
- ])
- ])
- ]
And now it is cleaner. So the lesson is, in a list of steps in a transition if you have a call to animate() with only the timing value without any styles then this animate() function will undo all the styles which we have applied
- style({ backgroundColor: 'yellow', opacity: 0 }),
over the period of time.
For the fadeIn effect we don’t really need backgroundColor, I just really use this for demonstration. So here is how we implement the fadeIn effect when an element transitions from the void state to the default(*) state. Initially we want to set its opacity to 0 which will make this element invisible and then over the period of time, the opacity will be changes to 1 which will make the elements appear on the view.
- animations: [
- trigger('fade', [
- transition('void => *', [
- style({ opacity: 0 }),
- animate(2000)
- ])
- ])
- ]
Implementing a Fade-out Animation
So here in this page if we add the new item, it will appear with fadeIn effect however if we click on the item it will appear immediately, there is no animation. So let’s see how to implement fadeout effect. So let’s go back to the fade trigger property. Now we define another transition from default(*) to void state because when we click an item, it’s going to be remove from the DOM. And at this point, it will go from the default(*) state to the void state.
- import { Component } from '@angular/core';
- import { trigger, transition, style, animate } from '@angular/animations';
- @Component({
- // tslint:disable-next-line:component-selector
- selector: 'todos',
- templateUrl: './todos.component.html',
- styleUrls: ['./todos.component.css'],
- animations: [
- trigger('fade', [
- transition('void => *', [
- style({ opacity: 0 }),
- animate(2000)
- ]),
- transition('* => void', [
- animate(2000, style({ opacity: 0 }))
- ])
- ])
- ]
- })
- export class TodosComponent {
- items: any[] = [
- 'Wash the dishes',
- 'Call the accountant',
- 'Apply for a car insurance'];
- addItem(input: HTMLInputElement) {
- this.items.splice(0, 0, input.value);
- input.value = '';
- }
- removeItem(item) {
- const index = this.items.indexOf(item);
- this.items.splice(index, 1);
- }
- }
Now let’s test this in the browser.
States
So it was the implementation of our fadeIn and fadeout effect. In this implementation, we can see something is duplicating here.
- animations: [
- trigger('fade', [
- transition('void => *', [
- style({ opacity: 0 }),
- animate(2000)
- ]),
- transition('* => void', [
- animate(2000, style({ opacity: 0 }))
- ])
- ])
- ]
Duplicated stuff:
- style({ opacity: 0 })
So how can we make this code cleaner?
If you pay closer attention, this is the style of void state. So when the element is out of the DOM, its opacity should be 0. So to cleanup this code we can define the style with the void state. So earlier we discussed that here in the trigger() we often have calls with the transition and/or state() function. So here we’ll define the state() function to define the state. And the state is void. The next parameter is,
The type of the 2nd parameter is AnimationStyleMetadata which might sound little bit confusing. And in fact, a lot of functions in the Animations Module look something like this. So they always have Animations…..Metadata. Here is a tip for you whenever you see types like that drop the Animations and Metadata word (AnimationsStyleMetadata) and when you drop this then we have the word Style which means we call the style function to get a style object.
- import { Component } from '@angular/core';
- import { trigger, transition, style, state, animate } from '@angular/animations';
- @Component({
- // tslint:disable-next-line:component-selector
- selector: 'todos',
- templateUrl: './todos.component.html',
- styleUrls: ['./todos.component.css'],
- animations: [
- trigger('fade', [
- state('void', style({ opacity: 0 })),
- transition('void => *', [
- animate(2000)
- ]),
- transition('* => void', [
- animate(2000)
- ])
- ])
- ]
- })
So once again inside the trigger we often have calls to the state and/or transition function. Most of the time we use transition functions but depending upon what we’re implementing we may use the state function to make our code cleaner and more maintainable.
Transitions
We still have little bit of duplication in our code.
- transition('void => *', [
- animate(2000)
- ]),
- transition('* => void', [
- animate(2000)
- ])
Look we have repeated animate(2000) in 2 places. So let’s see the cleaner way to implement the fadeIn and fadeout effect. In the transition function as you know, we can supply multiple state changes.
- animations: [
- trigger('fade', [
- state('void', style({ opacity: 0 })),
- transition('void => *, * => void', [
- animate(2000)
- ])
- ])
- ]
But we can make this even more clean. So instead of having 2 unidirectional state changes expressions, we can use Bi-directional state change expression
- transition('void <=> *', [
- animate(2000)
- ])
This is much better from where we started. So if we have multiple transitions and these transitions have the same implementation, we can refactor them into one transition with multiple state change expressions. Also here we have couple of aliases, but first let’s revert it back.
- transition('void => *, * => void', [
- animate(2000)
- ])
These two state expressions are very common. So in Angular we have the alias for these expressions. So when the element transitions from the void state to default state, our alias is :enter. And for the 2nd expression our alias is :leave. So when the element is leaving the DOM. So using these aliases is more cleaner and readable then bi-directional state change expressions
- transition(':enter, :leave', [
- animate(2000)
- ])
Creating Reusable Triggers
So we have defined fade trigger in our todos component and chances are somewhere else in the application we may want to apply ‘fade’ effect to another element. We don’t want to repeat all this code. So it is better to extract this code and put it in different module that we can reuse in multiple places. So we add a new file ‘animations.ts’ in src/app folder. And in this file, we’re going to define a reusable animations. If you a lot of animations instead of one file, you want to create a directory and in that directory you can manage different files for different kinds of animations. But here is just an example for demonstration.
Back in the todos component, here we have trigger() function which is actually defined in @angular/animations module. And if you look at the return type of trigger() function, it returns AnimationTriggerMetadata object. And we have already discussed the tip, whenever you see the type like this drop the words (Animation & Metadata). So this trigger() function returns a trigger object and all we have to do is to export the trigger object from our animations module. So we cut the animations code and paste it into the new file and export it. And now our actual code looks like,
- import { trigger, transition, style, state, animate } from '@angular/animations';
- export let fade = trigger('fade', [
- state('void', style({ opacity: 0 })),
- transition(':enter, :leave', [
- animate(2000)
- ])
- ]);
Now we can reuse this fade trigger into multiple places. So back to our component and here in the animations array, we’ll add fade trigger.
- import { fade } from './../animations';
- import { Component } from '@angular/core';
- @Component({
- // tslint:disable-next-line:component-selector
- selector: 'todos',
- templateUrl: './todos.component.html',
- styleUrls: ['./todos.component.css'],
- animations: [
- fade
- ]
- })
This is how we can reuse our animations.
Now before going further, let’s build one more animation from what we have learned so far. So let’s add one more animation ‘slide’ in our ‘animations.ts’
- import { trigger, transition, style, state, animate } from '@angular/animations';
- export let slide = trigger('slide', [
- transition(':enter', [
- style({ transform: 'translateX(-10px)' }),
- animate(500)
- ]),
- transition(':leave', [
- animate(500, style({ transform: 'translateX(-100%)' }))
- ])
- ])
- export let fade = trigger('fade', [
- state('void', style({ opacity: 0 })),
- transition(':enter, :leave', [
- animate(2000)
- ])
- ]);
Now consume slide animation into our component,
- import { slide } from './../animations';
- @Component({
- // tslint:disable-next-line:component-selector
- selector: 'todos',
- templateUrl: './todos.component.html',
- styleUrls: ['./todos.component.css'],
- animations: [
- slide
- ]
- })
And one last thing to work this new animation.
- <div *ngIf="items" class="list-group" >
- <button type="button"
- @slide
- *ngFor="let item of items"
- (click)="removeItem(item)"
- class="list-group-item"
- >{{ item }}</button>
- </div>
Add this otherwise you’ll see a lot of errors in the browser console. Now let’s see the animation in action.
Easings
Note that when we click on the item, it slides to the left with the constant speed. But in real life Objects don’t move with constant speed i.e. if we drop the ball from the top of the building, the speed of this ball increases gradually or when you’re driving your car and push the break the speed of your car decreases gradually. So in real life objects don’t move at a constant speed. Now let’s see how to make this animation more interesting. So back to our slide animation and let’s take a look at :leave transition. So the first argument to this animate function we passed numbers for timing the animation
- transition(':leave', [
- animate(500, style({ transform: 'translateX(-100%)' }))
- ])
If you want more control over this timing, we should see the string
- animate('500', style({ ... }))
This string has 3 components. First component is the duration which is required. Second component is the optional which is delay. And finally the 3rd component of the string is Easing.
Easing is basically a function that determines the speed of an animation over time. In CSS, we have few standard easings.
So these are the standard easings defined in CSS. If you want to implement a custom easing, you need to use Cubic Bezier function. So this is basically a function that determines the shape of the curve, we pass four numbers and these numbers determine the shape of easing curve.
There is a tool that helps you to design the curve and then you’ll get the cubic Bezier function. Here we have GUI to design the curve and numbers dynamically changes in the function. Here we also can preview the movement of the animation and compare it with other available animation categories as well. So we can get the idea of how our animation will work on the webpage.
So here is the programmatic tip for you. Use the Ease-in function to move things out of the screen.
Now back to our animate function. So as we’re moving the component out of the screen so we’ll use ease-in.
- animate('0.5s 1s ease-in', style({ transform: 'translateX(-100%)' }))
And we don’t really need the delay so remove it,
- transition(':leave', [
- animate('0.5s ease-in', style({ transform: 'translateX(-100%)' }))
- ])
Now back in the browser and test the animation.
Now let’s see how to use cubic-bezier function. So copy the values from cubic-bezier.com, we have the function containing values and we can use this function where we add ease-in
- transition(':leave', [
- animate('0.5s cubic-bezier(0,.7,1,.63)', style({ transform: 'translateX(-100%)' }))
- ])
And now see what happens in the browser. Just feel the movement of the objects.
Keyframes
So we’ve implemented slide animation. But still we can do something better. So earlier we discussed animate.css library.
Here in this dropdownlist we have all kinds of interesting effects. We’ll work with bounceOutLeft effect.
Now let’s see how we implement this in Angular. 1 way is to define this transition and play with the animate and style functions but it is very time consuming and hard. Because you’ve to work with all kinds of styles and transformation until you get the desired effect. But these days, there a lot of examples out there we can reuse their code instead of building everything from scratch. So let’s go to the github page of animate.css and go to the source directory and so on. Here we can see the implementation of bounceOutLeft effect in CSS. Here we’re using @keyframes feature of CSS. With Keyframe, we can specify multiple frames for an application and in each frame we can apply the different style. Here is the example,
In this animation, we have 2 keyframes. The first keyframe is 20% from the beginning and to is the 2nd keyframe which is the end of the animation. More complex animations have more complex keyframes and on each keyframe we have obviously different style. Now what we need to do is to get these keyframes and apply them in an animation.
- transition(':leave', [
- animate('0.5s ease-out', keyframes([
- style({})
- ]))
- ])
keyframes() are defined in @angular/animations. It contains an array where we can multiple calls to the style() but here we have an additional property with each style offset. And if you move back to the github page 20% on the first keyframe is actually the offset of our style here.
- transition(':leave', [
- animate('0.5s ease-out', keyframes([
- style({ offset: .2 })
- ]))
- ])
Now on the github page, we have 2 styles on first keyframe. Now we’ll apply them here.
- transition(':leave', [
- animate('0.5s ease-out', keyframes([
- style({
- offset: .2,
- opacity: 1,
- transform: translate3d(20px, 0, 0)
- })
- ]))
- ])
Now instead of using translate3d, make it simpler
- transition(':leave', [
- animate('0.5s ease-out', keyframes([
- style({
- offset: .2,
- opacity: 1,
- transform: 'translateX(20px)'
- })
- ]))
- ])
So it is our first keyframe
- transition(':leave', [
- animate('0.5s ease-out', keyframes([
- style({
- offset: .2,
- opacity: 1,
- transform: 'translateX(20px)'
- }),
- style({
- offset: 1,
- opacity: 0,
- transform: 'translateX(-100%)'
- })
- ]))
- ])
So in the 2nd keyframe we’re moving outside of the screen. So basically what we have here is the combination of fadeout and slideout with the bouncing effect. Now test the result,
So this is how we use keyframes to build more complex animations and define various styles in each keyframe. And each keyframe has an offset property that determines the relative position of the keyframe on the beginning of the animation.
Creating Reusable Animations with animation()
Let’s review what we have done. When this main page loads our items slides left side of the screen. And when we click on an item, the item slides to the left of the screen. But if we want more customized animation i.e. when the page loads instead of slideIn effect, we want fadeIn effect and when we click on the item, its background turns into red and then we see the slideOut effect. So let’s see how we can implement them.
Back to our animations.ts, we defined the reusable trigger called slide and look at the implementation of the :leave transition
- animate('0.5s ease-out', keyframes([
- style({
- offset: .2,
- opacity: 1,
- transform: 'translateX(20px)'
- }),
- style({
- offset: 1,
- opacity: 0,
- transform: 'translateX(-100%)'
- })
- ]))
This is our slideout effect with some kind of bouncing. Now here I don’t want to apply red background because it only make sense in the context of the todo items. I want this to be reusable to use it in multiple places. So now we need custom triggers todo items. So let’s go to our template and change the animation.
- <div *ngIf="items" class="list-group" >
- <button type="button"
- @todoAnimation
- *ngFor="let item of items"
- (click)="removeItem(item)"
- class="list-group-item"
- >{{ item }}</button>
- </div>
Now in the todos.component.ts
- import { trigger, transition, style, state, animate, keyframes } from '@angular/animations';
- import { slide, fade } from './../animations';
- import { Component } from '@angular/core';
- @Component({
- // tslint:disable-next-line:component-selector
- selector: 'todos',
- templateUrl: './todos.component.html',
- styleUrls: ['./todos.component.css'],
- animations: [
- trigger('todoAnimation', [
- transition(':enter', [
- // Need fadeIn animation here.
- ]),
- transition(':leave', [])
- ])
- ]
- })
Now we need fadeIn animation here in but we already define this in animations.ts. So it is the problem that we already defined it and export it. We have entire trigger
- export let fade = trigger('fade', [
- state('void', style({ opacity: 0 })),
- transition(':enter, :leave', [
- animate(2000)
- ])
- ]);
And we can’t use a trigger inside a transition. So temporarily I’m going to duplicate the code in a slightly different way in the component. And after we’ll refactor this.
- animations: [
- trigger('todoAnimation', [
- transition(':enter', [
- // Need fadeIn animation here.
- style({ opacity: 0}),
- animate(2000)
- ]),
- transition(':leave', [])
- ])
- ]
Now what about the leave transition. Open the animations.ts. Here we have developed the leave transition and here we have implemented the bounceOutLeft animation and it is really very complicated having couple of keyframes with lots of details. So I don’t want to duplicate this and use so many places. So let’s see how to extract this code, put it somewhere else and then reuse it in multiple places. So first off cut the entire animate() function from leave transition and make another export variable and apply all the stuff into another animation() function
- import { trigger, transition, style, state, animate, keyframes, animation, useAnimation } from '@angular/animations';
- export let bounceOutLeftAnimation = animation(
- animate('0.5s ease-out', keyframes([
- style({
- offset: .2,
- opacity: 1,
- transform: 'translateX(20px)'
- }),
- style({
- offset: 1,
- opacity: 0,
- transform: 'translateX(-100%)'
- })
- ]))
- );
- export let slide = trigger('slide', [
- transition(':enter', [
- style({ transform: 'translateX(-10px)' }),
- animate(500)
- ]),
- transition(':leave', [
- useAnimation(bounceOutLeftAnimation)
- ])
- ]);
animation() function is used to create the Reusable function. Now back to our leave transition trigger. We use helper function useAnimation() and use this export variable into it.
Now to make this code even more clean, we can get rid of this square bracket

Muthu KumarPosted Jan 3, 2019, 10:41 PM
Really very nice article sir. Detailed explanation awesome. Thanks for sharing..
Sarathlal SaseendranPosted Dec 12, 2018, 2:09 AM
Awesome article Usama. Absolutely brilliant effort. I will tell my friends to read your angular articles for their reference. If possible, try to make a PDF on Angular. You have all stuff.
Mahesh ChandPosted Dec 11, 2018, 9:30 PM
WOW! Great article and this is definitely not an overview. It's pretty detailed.