Angular Pagination: Customizing Scrolling Behavior through Scroll Event

ANGULAR ROUTER EXTRA OPTIONS

Ayyash Ayyash
2 min readApr 7, 2022

In the previous post I made a continuous pagination solution based on route parameters. The problem we finally faced was the scrollPositionRestoration related issue. It is set to enabled as recommended, which scrolls the page up on forward navigation. The "next" click, is considered a forward navigation.

Navigate with custom scrolling behavior

The scrolling behavior via Scroll event is vaguely documented in Angular scrollPositionRestoration:

— Quote:

Configures if the scroll position needs to be restored when navigating back.

  • disabled (Default) Does nothing. Scroll position is maintained on navigation.
  • top Sets the scroll position to x = 0, y = 0 on all navigation.
  • enabled Restores the previous scroll position on backward navigation, else sets the position to the anchor if one is provided, or sets the scroll position to 0, 0 (forward navigation). This option will be the default in the future.

You can implement custom scroll restoration behavior by adapting the enabled behavior as in the following example.

class AppModule {
constructor(router: Router, viewportScroller: ViewportScroller) {
router.events.pipe(
filter((e: Event): e is Scroll => e instanceof Scroll)
).subscribe(e => {
if (e.position) {
// backward navigation
viewportScroller.scrollToPosition(e.position);
} else if (e.anchor) {
// anchor navigation
viewportScroller.scrollToAnchor(e.anchor);
} else {
// forward navigation
viewportScroller.scrollToPosition([0, 0]);
}
});
}
}

— End quote.

What we want to accomplish is the same behavior except when we are paginating. First, the scrollPositionRestoration must be set to disabled.

In app.route.ts:

@NgModule({
// disable scroll position auto handling to override
imports: [
RouterModule.forRoot(routes, {
scrollPositionRestoration: 'disabled',
}),
],
exports: [RouterModule],
})
export class AppRouteModule {
// copy code from Angular
constructor(router: Router, viewportScroller: ViewportScroller) {
router.events.pipe(filter((event) => event instanceof Scroll)).subscribe({
next: (e: Scroll) => {
if (e.position) {
// backward navigation
viewportScroller.scrollToPosition(e.position);
} else if (e.anchor) {
// anchor navigation
viewportScroller.scrollToAnchor(e.anchor);
} else {
// forward navigation
// check url if page exists do not scroll
if (!e.routerEvent.urlAfterRedirects.includes('page')) {
viewportScroller.scrollToPosition([0, 0]);
}
}
},
});
}
}

So, if the “page” exists in the url, the view port won’t scroll up to 0. This actually works. Until you have a link to a page that has the term “page” in it! You probably want to be more specific in what the url contains. For my simple blog, I am happy with this solution.

Do you have other ideas? Do you do your pagination differently? Please let me know.

Resources

--

--

Ayyash Ayyash

Freelance UX developer, thus free to travel and work from anywhere on Earth