SchmitzCatz
SchmitzCatz

Reputation: 11

Angular 11 child route animation is not working

I recently ran into some problems regarding child route animation in a conditionally displayed (*ngif) parent element (see here). To resolve this issue, I created a small sample project, in order to evalute a clean solution for this and transfer it back to the original project. However, router animation now does not work at all as intended, even in this very basic sample project.

The animation plays on page-load but not when changing routes (it just displays the corresponding child route).

I followed the instruction from angular and followed this tutorial. I searched the web, but did not find an answer to my problem. Moreover, I have checked multiple times, if I made any mistake, but I cant seem to find one.

app.module.ts

I imported all components and modules as follows:

@NgModule({
  declarations: [
    AppComponent,
    ParentComponent,
    Child1Component,
    Child2Component,
    Child3Component,
    Child4Component
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})

app-routing.module.ts

I declared the routes as follows:

const routes: Routes = [
  { path: '', redirectTo: 'p', pathMatch: 'full' },
  {
    path: 'p', component: ParentComponent,
    children: [
      { path: '', redirectTo: 'c1', pathMatch: 'full' },
      { path: 'c1', component: Child1Component, data: { animation: 'toleft' } },
      { path: 'c2', component: Child2Component, data: { animation: 'toleft' } },
      { path: 'c3', component: Child3Component, data: { animation: 'toleft' } },
      { path: 'c4', component: Child4Component, data: { animation: 'toleft' } },
    ]
  }
];

app.components.html

<div><a routerLink="/p/c1">C1</a></div>
<div><a routerLink="/p/c2">C2</a></div>
<div><a routerLink="/p/c3">C3</a></div>
<div><a routerLink="/p/c4">C4</a></div>
<app-parent></app-parent>

parent.component.html

<div
  [@routeAnimations]="prepareRoute(outlet)"
  style="position: relative;"
>
  <router-outlet #outlet="outlet"></router-outlet>
</div>

parent.component.ts

import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
import { Router, RouterOutlet } from '@angular/router';
import { fader } from '../animation';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.scss'],
  animations: [
    fader,
  ]
})
export class ParentComponent implements OnInit {
  constructor() { }
  ngOnInit(): void { }

  public prepareRoute = (outlet: RouterOutlet) => {
    return outlet && outlet.activatedRouteData && outlet.activatedRouteData.animation;
  }
}

animation.ts

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

export const fader =
  trigger('routeAnimations', [
    transition('* <=> *', [
      // Set a default  style for enter and leave
      query(':enter, :leave', [
        style({
          position: 'absolute',
          left: 0,
          width: '100%',
          opacity: 0,
          transform: 'scale(0) translateY(100%)',
        }),
      ], { optional: true }),
      // Animate the new page in
      query(':enter', [
        animate('600ms ease', style({ opacity: 1, transform: 'scale(1) translateY(0)' })),
      ], { optional: true })
    ]),
  ]);

Upvotes: 0

Views: 1801

Answers (1)

Andrei
Andrei

Reputation: 12036

[@routeAnimations]="prepareRoute(outlet)" and transition('* <=> *' means that route animation will "activate" if the prepareRoute(outlet) changes its value. as I see in your case it can change from 'toleft' to 'toleft'. make different animations names so angular would know which animations to run. for example

{...page1, data: {animation: 'level1-page'}},
{...page2, data: {animation: 'level2-page'}},
transition('level1-page => level2-page', toLeftAnimation),
transition('level2-page => level1-page', toRightAnimation)

Upvotes: 1

Related Questions