diff --git a/apps/openchallenges/app/src/app/app.config.ts b/apps/openchallenges/app/src/app/app.config.ts index f3c8a37977..e90f6700ea 100644 --- a/apps/openchallenges/app/src/app/app.config.ts +++ b/apps/openchallenges/app/src/app/app.config.ts @@ -49,8 +49,9 @@ export const appConfig: ApplicationConfig = { routes, withEnabledBlockingInitialNavigation(), withInMemoryScrolling({ - scrollPositionRestoration: 'top', + scrollPositionRestoration: 'enabled', }) + // withDebugTracing() ), ], }; diff --git a/libs/openchallenges/challenge-search/src/lib/challenge-search.component.html b/libs/openchallenges/challenge-search/src/lib/challenge-search.component.html index 5ca5f733ff..52e688af20 100644 --- a/libs/openchallenges/challenge-search/src/lib/challenge-search.component.html +++ b/libs/openchallenges/challenge-search/src/lib/challenge-search.component.html @@ -1,4 +1,4 @@ -
+
@@ -52,7 +52,7 @@

Challenges

[toggleable]="true" [collapsed]="statusFilter.collapsed" > - { + // After the route change is complete, restore the scroll position + window.scrollTo(0, currentScrollPosition); + }); } onSubmissionTypesChange(selected: string[]): void { diff --git a/libs/shared/typescript/util/src/lib/directives/disable-scroll-position-restoration.directive.ts b/libs/shared/typescript/util/src/lib/directives/disable-scroll-position-restoration.directive.ts new file mode 100644 index 0000000000..08afe2948a --- /dev/null +++ b/libs/shared/typescript/util/src/lib/directives/disable-scroll-position-restoration.directive.ts @@ -0,0 +1,49 @@ +import { ViewportScroller } from '@angular/common'; +import { Directive, OnInit, DestroyRef } from '@angular/core'; +import { Router, Scroll } from '@angular/router'; +import { filter, map, switchMap, BehaviorSubject, tap } from 'rxjs'; + +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; + +@Directive({ + selector: '[sageDisableScrollPositionRestoration]', + standalone: true, +}) +export class DisableScrollPositionRestorationDirective implements OnInit { + shouldScroll = new BehaviorSubject(false); + private readonly shouldScroll$ = this.shouldScroll.asObservable(); + + constructor( + private router: Router, + private viewportScroller: ViewportScroller, + private destroyRef: DestroyRef + ) {} + + ngOnInit() { + const position$ = this.router.events.pipe( + tap((ss) => console.log(ss)), + filter((event: any) => event instanceof Scroll), + map((event: Scroll) => event.position) + ); + + position$ + .pipe( + switchMap((position) => + this.shouldScroll$.pipe( + filter(Boolean), + map(() => position) + ) + ), + takeUntilDestroyed(this.destroyRef) + ) + .subscribe({ + next: (position) => { + this.viewportScroller.scrollToPosition(position || [0, 0]); + }, + }); + } + + ngAfterViewInit(): void { + this.shouldScroll.next(true); + } +} diff --git a/libs/shared/typescript/util/src/lib/directives/disable-scroll-position-restoration.spec.ts.off b/libs/shared/typescript/util/src/lib/directives/disable-scroll-position-restoration.spec.ts.off new file mode 100644 index 0000000000..81c5abaa11 --- /dev/null +++ b/libs/shared/typescript/util/src/lib/directives/disable-scroll-position-restoration.spec.ts.off @@ -0,0 +1,8 @@ +import { DisableScrollPositionRestorationDirective } from './disable-scroll-position-restoration.directive'; + +describe('DisableScrollPositionRestorationDirective', () => { + it('should create an instance', () => { + const directive = new DisableScrollPositionRestorationDirective(); + expect(directive).toBeTruthy(); + }); +});