DEV Community

Cover image for Angular Pagination: Customizing Scrolling Behavior through Scroll Event
Ayyash
Ayyash

Posted on • Originally published at garage.sekrab.com

Angular Pagination: Customizing Scrolling Behavior through Scroll Event

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]);
      }
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

--- 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]);
          }
        }
      },
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

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

Discussion (0)