Search code examples
angular6angular-router

Set URL fragment on browser Back navigation in Angular


Is it possible to customize the back behavior of the Angular router? Specifically, I'd like to add a URL fragment based on the resource the browser is navigating from.

For example, if the browser is on http://example.com/purchases/42, navigating back would take the user to http://example.com/purchases#42 instead of http://example.com/purchases. This is desirable because the /purchases page could be very long, and the URL fragment could position the browser in the context of the previous page.

Is such a thing even possible? Is the only way this could be accomplished is by using the History API, or is there some other API that Angular users for managing navigation state?


Solution

  • Well, lucky for you, in the new Angular 6.1 there is a new feature for routers that you can enable and your router will "remember" your last scroll position when you hit back.
    You have to set the routers module like that:

    RouterModule.forRoot(routes, {
        scrollPositionRestoration: 'enabled'
      })
    

    There problem right now is that its a very new feature, and its will only work for static pages. Thats mean that if you fetching content from service or something, the restoration will try to set it self before you actually have the data, so the position will fail. (Currently, it will also fail even if you are using a resolver)

    There is a workaround that we can use right now via the new service called viewportScroller from the @angular/router package, but you will have to do it manully. (currently, it will probably get fixed in the near future).

    export class PendingRacesComponent {
      scrollPosition: [number, number];
      races: Array<RaceModel>;
    
      constructor(route: ActivatedRoute, private router: Router, private viewportScroller: ViewportScroller) {
        this.races = route.snapshot.data['races'];
        this.router.events.pipe(
          filter(e => e instanceof Scroll)
        ).subscribe(e => {
          if ((e as Scroll).position) {
            this.scrollPosition = (e as Scroll).position;
          } else {
            this.scrollPosition = [0, 0];
          }
        });
      }
      ngAfterViewInit() {
        this.viewportScroller.scrollToPosition(this.scrollPosition);
      }
    }
    

    This is an example of how you can use it right now, for full explanation you should visit the post