Summary
The page navigation in Angular 21 triggers the leave animation of a child component even though the parent component is being destroyed. This unexpected behaviour causes visual glitches and can confuse users. The root cause is that the new animation API treats page navigation as a component transition that still runs all defined exit animations unless explicitly suppressed.
Root Cause
- Animation precedence:
animate.leaveis triggered whenever a component is removed from the DOM, regardless of whether the removal is due to navigation or a parent component’s lifecycle. - Angular Router integration: The router’s navigation does not automatically set
$animate: 'none'or prevent exit animations on nested components. - Lack of automatic guard: Older animations packages used a detach mechanism that implicitly cancelled nested animations upon navigation. The modern API removed this shortcut to give developers more explicit control.
Why This Happens in Real Systems
- In production, side‑effects such as API calls or state cleanup are often coupled to angular lifecycle hooks.
- If a child animation runs during navigation, it can:
- Delay route changes, causing a perceptible lag.
- Leave stale visual states on the bucket pages.
- Increase CPU/GPU usage on mobile devices during rapid navigation.
Real-World Impact
- Users experience flickering or a partial fade effect during tab changes.
- Automated tests encounter intermittent failures when asserting DOM states at navigation boundaries.
- Performance dashboards show a spike in rendering time on pages with heavy animations.
Example or Code (if necessary and relevant)
No code is required for this explanation.
How Senior Engineers Fix It
- Explicit animation control: Add a flag that is set to
falseduring navigation, and conditionally execute the animation.// In component isNavigating = false; afterNavigate() { this.isNavigating = true; } - Use
@Componentanimationsguard: Leverage route guards to cancel animations by returningfalsefromcanDeactivate. - Leverage Angular’s animation API features:
animatewith aquery('[ng-reflect-animate]', [], { optional: true })to opt out of nested animations.animateChild()andquery('@*', [...], { optional: true })to control nested child animations selectively.
Key takeaway: Always add a navigation check or guard around exit animations to keep the user interface consistent and performant.
Why Juniors Miss It
- Assumption of automatic cancellation: Junior developers often rely on older behavior where nested animations were automatically stopped during navigation.
- Underestimating lifecycle interplay: They may not recognize that Angular’s router treats navigation as a transition that still triggers all exit animations.
- Neglecting performance checks: Focusing on visual fidelity can lead to overlooking subtle performance regressions caused by unintended animation playbacks.
By following the mature patterns above, senior engineers can ensure that page navigations are smooth and animation logic does not interfere with the intended user experience.