Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vonbeitthia/304a09fccf556b2ef82bcc91412e0189 to your computer and use it in GitHub Desktop.
Save vonbeitthia/304a09fccf556b2ef82bcc91412e0189 to your computer and use it in GitHub Desktop.
Custom scroll position restoration logic for Angular 2+, that doesn't consider query parameter changes in route as forward navigation, thus preventing certain scenarios where you don't want query parameter changes to scroll-to-top as they would with 'scrollPositionRestoration: enabled'.
export class AppModule {
constructor(private router: Router, private viewportScroller: ViewportScroller) {
this.handleScrollOnNavigation();
}
/**
* When route is changed, Angular interprets a simple query params change as "forward navigation" too.
* Using the pairwise function allows us to have both the previous and current router events, which we can
* use to effectively compare the two navigation events and see if they actually change route, or only
* the route parameters (i.e. selections stored in query params).
*
* Related to: https://github.com/angular/angular/issues/26744
*/
private handleScrollOnNavigation(): void {
this.router.events.pipe(
// import { Event } from '@angular/router'
filter((e: Event): e is Scroll => e instanceof Scroll),
pairwise()
).subscribe((e: Scroll[]) => {
const previous = e[0];
const current = e[1];
if (current.position) {
// Backward navigation
this.viewportScroller.scrollToPosition(current.position);
} else if (current.anchor) {
// Anchor navigation
this.viewportScroller.scrollToAnchor(current.anchor);
} else {
// Check if routes match, or if it is only a query param change
if (this.getBaseRoute(previous.routerEvent.urlAfterRedirects) !== this.getBaseRoute(current.routerEvent.urlAfterRedirects)) {
// Routes don't match, this is actual forward navigation
// Default behavior: scroll to top
this.viewportScroller.scrollToPosition([0, 0]);
}
}
});
}
private getBaseRoute(url: string): string {
// return url without query params
return url.split('?')[0];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment