Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing query params - page scrolls top, Angular

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

like image 873
Lukas Junokas Avatar asked Jan 27 '23 04:01

Lukas Junokas


2 Answers

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

like image 141
benshabatnoam Avatar answered Jan 28 '23 19:01

benshabatnoam


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] );
        }
      }
    } );
  }
}
like image 45
Jeremias Nater Avatar answered Jan 28 '23 19:01

Jeremias Nater