Unexpected behavior: Angular 4 animation not activating

Within my current project, I've implemented the following:

slideInOut.ts

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

export const slideInOut = trigger('slideInOut', [
  state('*', style({
    transform: 'translateX(0)'
  })),

  // Transition for route 'enter'
  transition(':enter', [
    style({
      transform: 'translateX(100%)'
    }),
    animate('.3s ease-in-out', style({
      transform: 'translateX(0)'
    }))
  ]),

  // Transition for route 'leave'
  transition(':leave', [
    animate('.3s ease-in-out', style({
      transform: 'translateX(100%)'
    }))
  ])
]);

home.component.ts

import { Component } from '@angular/core';
import { slideInOut } from '../../animations/slideInOut';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  animations: [
    slideInOut
  ],
  styleUrls: ['./home.component.css']
})
export class HomeComponent {
  constructor() {}
}

home.component.html

<div @slideInOut>
  <button [routerLink]="['', { outlets: {'aux': null} }]">Test</button>
</div>

Despite the successful entry animation of my component, the exit animation fails to trigger. The component slides in correctly but does not slide out. It appears for .3s and vanishes abruptly. Various CSS properties have been tested instead of transform, with no success. Also tried substituting :leave with * => * and * => void without luck. Any suggestions? Thank you!

Answer №1

The reason why your :leave animation fails to occur is due to the route change, which also affects your "canvas"/component.

On the other hand, the :enter trigger works smoothly because the animation is specified within the currently active route. When you navigate to that route, the "canvas" is already present from the start.

To solve this issue, you need to think creatively and consider using

<router-outlet></router-outlet>
.

One approach is to wrap the router-outlet within a container div for animation purposes. The trigger for this animation will be the changes in routes, which you can monitor in various ways.

To differentiate between routes, data has been added to them as shown below:

const routes: Routes = [
  { path: 'home', component: HomeComponent, data: { state: 'home' }  },
  { path: 'about', component: AboutComponent, data: { state: 'about' } },
];

In the app.component.html file, you can wrap the router-outlet like this:

<main [@routerTransition]="getState(o)">
  <router-outlet #o="outlet"></router-outlet>
</main>

The getState() function in the app.component.ts file manages route change detection and triggers the animations:

getState(outlet) {
  // Changing the activatedRouteData.state triggers the animation
  return outlet.activatedRouteData.state;
}

Lastly, the animation is simply linked to the app component's decorator:

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  animations: [
    trigger('routerTransition', [
      transition('* <=> *', [    
        query(':enter, :leave', style({ position: 'fixed', width:'100%' })),
        group([ 
          query(':enter', [
            style({ transform: 'translateX(100%)' }),
            animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))
          ]),
          query(':leave', [
            style({ transform: 'translateX(0%)' }),
            animate('0.5s ease-in-out', style({ transform: 'translateX(-100%)' }))]),
        ])
      ])
    ])
   ],
})

You can see this concept in action here:

StackBlitz Example

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can we use type mapping and conditional types to make it mandatory for an object to have certain specified keys?

Someone sent over a type definition from a 3rd party library: interface UpdateRequest { data?: ValueRange[]; options?: Options } I am trying to implement a method with the following signature: update(params: RequiredOnly<UpdateRequest, 'dat ...

Function useAppDispatch is missing a return type

.eslintrc.js module.exports = { root: true, extends: [ '@react-native-community', 'standard-with-typescript', 'plugin:@typescript-eslint/recommended', 'plugin:jest/recommended', 'plugin:p ...

Encountering difficulties with Bootstrap toggle functionality in Angular 2.0 following the establishment of a MEAN stack

While setting up a MEAN stack app following a tutorial, everything was going smoothly until I decided to test some Bootstrap components from their site. After installing Bootstrap in the index.html file for Angular, I noticed that Bootstrap was being loade ...

Using TypeScript to Add Items to a Sorted Set in Redis

When attempting to insert a value into a sorted set in Redis using TypeScript with code like client.ZADD('test', 10, 'test'), an error is thrown Error: Argument of type '["test", 10, "test"]' is not assigna ...

Tips on executing an asynchronous operation before exiting

I have been attempting to execute an asynchronous operation before my process ends. By 'ends', I mean in every instance of termination: ctrl+c Uncaught exception Crashes End of code Anything.. As far as I know, the exit event handles this for ...

Why is it that AoT chooses to lower this value?

I am facing an issue with environment variables in my angular 5 project. I have been using a common.ts file in the environment/ folder like this: environment.prod.ts import common from './common/common'; export const environment: any = { ... c ...

Despite making changes to the model, the Angular UI fails to redraw despite using NgZone

I'm facing a challenge where I need to fetch input values from an external source outside of Angular. These values are used to trigger a service in my Angular module that retrieves relevant data from the backend. While the subscribe function works wel ...

What is the process for linking a Python Flask CAS server with an Angular application?

After successfully setting up the python server (Flask to be specific) and establishing a successful connection to my CAS server, it is working flawlessly by redirecting to CAS login and returning accurate user data upon login. Here is the relevant code sn ...

Running multiple instances of an Angular2 module on a single page using Bootstrap

I have a unique situation where my web forms application dynamically loads User controls onto a page using configurations, similar to a CMS with re-usable widgets. I'm interested in implementing one of these user controls as an Angular2 component. &l ...

Customize column header values for Excel/CSV export with ag-grid

In my application, I am utilizing ag-grid which includes two buttons 'Download Excel' and 'Download CSV' at the top of the grid. When a user clicks on either button, the data from the grid should be downloaded in the respective file for ...

Guide to Rolling a Set of 5 Dice

I am looking to develop a game involving 5 dice. I have already created a function to roll one die using a random method, but I am unsure how to extend this functionality to the remaining four dice without having to create a separate method for each one. ...

TypeScript and the Safety of Curried Functions

What is the safest way to type curried functions in typescript? Especially when working with the following example interface Prop { <T, K extends keyof T>(name: K, object: T): T[K]; <K>(name: K): <T>(object: T) => /* ?? */; ...

Tips for validating the upload functionality of a .csv file using Protractor

I'm currently testing the upload functionality of a csv file in protractor. Below is the code I am using: const absPath = path.resolve(__dirname, 'csvFile.csv'); const fileInput = element(by.css('input[type=file]')); browser.wait ...

Error encountered: 'applePaySession.completeMerchantValidation' is not a valid object reference when attempting to process a successful apple pay payment

So, I'm having an issue with the user's payment going through but encountering undefined value when checking compatibility. I've been trying to debug this problem in my code snippet below: setCanDisplayApplePay() { var client = n ...

Revitalize Angular 2 component

As a newcomer to angular 2, I am eager to expand my knowledge of it. The main question on my mind is: How can we refresh a component (re-invoke ngOnInit). Within this component lies the functionality to fetch data from a database through an API call. Add ...

The Angular Observable is throwing an error that is unknown and cannot be assigned, specifically

I'm currently building a todo app with Angular 8 and using Firebase as the backend for my project. In my todo service file, I encountered an error message that reads: Type `Observable unknown[]` is not assignable to type `Observable ITodo[]`. Type ...

Unable to retrieve the reflective metadata of the current class instance

Is it possible to retrieve the reflect-metadata from an instance of a class? The documentation provides examples that suggest it should be achievable, but when I attempt to do so, I receive undefined as a result. Strangely enough, when I request the metada ...

Utilize the authenticated page across various tests in Playwright for efficient testing

Starting out fresh with playwright and node.js frameworks Currently in the process of developing a framework using playwright with typescript. Everything was smooth sailing until I reached the point where I needed to run my tests sequentially on the same ...

Tips for creating a linear movement effect for a collection of objects

I am working on animating a linear gripping motion for picking and placing objects. Here is a codesandbox link where you can see the issue I am facing: https://i.sstatic.net/dUdPv.png The gripper is created, moves down to reach the LEGO brick, and then s ...

What are some strategies for locally developing Angular 7 libraries that have dependencies on one another? (Troubleshooting npm linking)

I am managing two Angular library NPM packages: A contains basic components A-BC includes components that enhance the ones in A, with additional features to interact with the BC library Some components in A-BC are imported from A like import { MyThing } ...