4

I'm using this code to make my app scroll to top when changing routes, everything works fine, but i would like to disable this option when changing query params. I have angular material tabs and my query params define which tab should be opened when visiting page, but when i change tab (also changes url) it automatically scrolls top

I think it is impossible to do it easy way, but maybe you have answer

  imports: [RouterModule.forRoot(routes, {
    scrollPositionRestoration: 'enabled',
    anchorScrolling: 'enabled'
  })]

I want when changing only tabs the app wouldn't scroll top

Lukas Junokas
  • 91
  • 1
  • 9
  • hope this helps you : https://stackoverflow.com/questions/46658522/how-to-smooth-scroll-to-page-anchor-in-angular-4-without-plugins-properly/51400379#51400379 – Joel Joseph Jun 19 '19 at 08:25

2 Answers2

6

Looking at the property scrollPositionRestoration documentation, found this:

You can implement custom scroll restoration behavior by adapting the enabled behavior...

Implementation:

  1. Remove added code:
{
  scrollPositionRestoration: 'enabled',
  anchorScrolling: 'enabled'
}

Leaving it as:

imports: [RouterModule.forRoot(routes)]
  1. Add the following code to app.module.ts:
import { Event, Scroll, Router } from '@angular/router';
import { ViewportScroller } from '@angular/common';

export class AppModule {
  constructor(router: Router, viewportScroller: ViewportScroller) {
    router.events.pipe(
      filter((e: Event): e is Scroll => e instanceof Scroll)
    ).subscribe(e => {
      // here you'll have your own logic, this is just an example.
      if (!router.url.includes('hello')) {
        viewportScroller.scrollToPosition([0, 0]);
      }
    });

  }
}

Here is a DEMO for reproducing your issue.

And this is a DEMO resolving it with this solution.

Cheers

benshabatnoam
  • 7,161
  • 1
  • 31
  • 52
3

Finally i found the working solution which does not scroll on query param change here

It works pretty cool using the pairwise pipe-operator alongside the filter, which lets you compare the last emitted value matching the filter to the current one.

My own Complete working snippet:

export class AppModule {
  constructor( private router: Router, private viewportScroller: ViewportScroller ) {
    this.router.events.pipe(
      filter( ( e: Event ): e is Scroll => e instanceof Scroll ),
      pairwise()
    ).subscribe( ( eventPair ) => {
      const previousEvent = eventPair[ 0 ];
      const event = eventPair[ 1 ];
      if ( event.position ) {
        // backward navigation
        this.viewportScroller.scrollToPosition( event.position );
      } else if ( event.anchor ) {
        // anchor navigation
        this.viewportScroller.scrollToAnchor( event.anchor );
      } else {
        // forward navigation
        if ( (previousEvent.routerEvent.urlAfterRedirects.split( '?' )[ 0 ]) !== event.routerEvent.urlAfterRedirects.split( '?' )[ 0 ] ) {
          // Routes don't match, this is actual forward navigation
          // Default behavior: scroll to top
          this.viewportScroller.scrollToPosition( [0, 0] );
        }
      }
    } );
  }
}
Jeremias Nater
  • 650
  • 3
  • 18