2

I have set up a slide animation in Angular 7 when changing the route. The problem I have right now is that the animation is stuttering, because the Component that I'm navigating to is executing code during the animation in the OnInit lifecycle.

How do I initialize code for the component after the animation has finished to prevent frame drops?

Edit:

I'm using router animations, here's my setup:

app.component.html:

<div [@routeAnimations]="prepareRoute(outlet)">
  <router-outlet #outlet="outlet"></router-outlet>
</div>

app.component.ts:

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  animations: [routeAnimations]
})
export class AppComponent {
  prepareRoute(outlet: RouterOutlet) {
    return outlet && outlet.activatedRouteData && outlet.activatedRouteData.animation;
  }
}

app-routing.module.ts:

const routes: Routes = [
  {
    path: 'sign-in',
    loadChildren: './modules/sign-in/sign-in.module#SignInModule',
    data: {animation: 'slideLeft'}
  },
  {
    path: 'dashboard',
    component: DashboardComponent,
    data: {animation: 'slideRight'}
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

animations.ts:

export const routeAnimations =
  trigger('routeAnimations', [
    transition('slideLeft => slideRight', [
      // ...a bunch of animation code...
    ]),
    transition('slideRight => slideLeft', [
      // ...a bunch of animation code...
    ])
  ]);
HitomiTenshi
  • 514
  • 2
  • 6
  • 20
  • You may find this article much helpful: [https://alligator.io/angular/animation-callbacks/](https://alligator.io/angular/animation-callbacks/) – Harun Yilmaz Jan 08 '19 at 20:37
  • @HarunYılmaz I already saw this, this isn't really helpful as the animation start and end events are fired for a single component using angular animations. I'm using router animations and need OnInit code for each component I'm navigating to. The OnInit code needs to run after the router animation though. – HitomiTenshi Jan 08 '19 at 20:41

1 Answers1

5

You will need to expose the start and done events from the animation to child components.

@Component({..})
export class AppComponent {
    public start$: Subject<AnimationEvent> = new Subject();
    public done$: Subject<AnimationEvent> = new Subject();
}

<div [@routeAnimations]="prepareRoute(outlet)"
     (@routeAnimations.start)="start$.next($event)"
     (@routeAnimations.done)="done$.next($event)">
   <router-outlet #outlet="outlet"></router-outlet>
</div>

Now inject the AppComponent into child components used in the router.

@Component({..})
export class ChildComponent implements OnDestroy {
    private readonly _destroyed: Subject<void> = new Subject();
    public constructor(app: AppComponent) {
        app.done$
           .pipe(first(), takeUntil(this._destroyed))
           .subscribe(()=> {
               // do special work here
           });
    }
    public ngOnDestroy() {
        this._destroyed.next();
    }
}
Reactgular
  • 52,335
  • 19
  • 158
  • 208