All topics
Routingintermediate

Router Events

Explain the Router's event stream and how to use it for loading indicators, analytics, and scroll restoration.

The Router emits a sequential stream of events for every navigation attempt — NavigationStart, various guard/resolve events, NavigationEnd, NavigationCancel, NavigationError, among others — exposed as an Observable on the injected Router service's .events property. Interviewers ask about this because it's the mechanism behind several very common, very visible app features: top-of-page loading bars, page-view analytics tracking, and scroll-position restoration.

It's like an airport's flight status board broadcasting every stage of a flight — boarding, departed, delayed, landed, cancelled — letting anyone (an app displaying arrivals, a family tracking a relative's flight) react to exactly the milestones they care about without needing direct radio contact with the cockpit.

Key Concepts

1
A typical pattern subscribes to router.events, filters for the specific event types of interest using RxJS's filter operator combined with an instanceof check (since all router events share a common base but are distinguished by class), and reacts accordingly — showing a progress bar on NavigationStart and hiding it on NavigationEnd/NavigationCancel/NavigationError, or firing an analytics pageview call specifically on NavigationEnd (since that's the event guaranteed to fire only once navigation has actually completed successfully).
router.eventsfilterinstanceofNavigationStartNavigationEnd
2
A deeper interview question probes the full event ordering for a single navigation — NavigationStartRoutesRecognized → guard-related events → GuardsCheckEnd → resolver-related events → ResolveEndNavigationEnd (or a cancel/error variant instead) — and understanding this ordering is what lets you correctly place logic that must run at exactly the right point, like only starting the loading spinner once guards begin evaluating.
NavigationStartRoutesRecognizedGuardsCheckEndResolveEndNavigationEnd
3
Worth mentioning: Angular's router also has a built-in scroll position restoration feature (withInMemoryScrolling() in provideRouter) that's implemented internally using this same event stream, which is a good concrete example to cite of the Router's own events driving real router behavior, not just application-level code reacting to them.
withInMemoryScrolling()provideRouter