Search code examples
angularangular-routingbrowser-history

After a Location.go(), History.back() does not trigger ActivatedRoute.paramMap


Consider this URL:

http://localhost:4200/items

I use Location.go() to update the URL when an element is opened (expanded) in my GUI:

http://localhost:4200/items;openedId=123

When I hit the back button, the URL is changed back to http://localhost:4200/items, but my subscription on ActivatedRoute.paramMap is not triggered. (and therefore my item is stays opened)

Oddly enough, it is triggered when I open two elements consecutively, and then hit back two times:

Open main page -> http://localhost:4200/items
Open item 123  -> http://localhost:4200/items;openedId=123
Open item 456  -> http://localhost:4200/items;openedId=456

Back to http://localhost:4200/items;openedId=123 -> ActivatedRoute.paramMap triggered
Back to http://localhost:4200/items -> ActivatedRoute.paramMap triggered (!)

Why isnt't it triggered the first time? Why do I need to have two history entries before it works? I am confused.

Update: This is how I listen for changes in the paramMap:

  public ngOnInit() {

    this.subscriptions.add(this.activatedRoute.paramMap.subscribe(paramMap => {
      this.handleNavigation(paramMap);
    }));
}

Solution

  • I've faced the same issue, I guess it's because the Router doesn't know about the location.go() navigation. So, location.go() changes location url to http://localhost:4200/items;openedId=123 but the router current url is still http://localhost:4200/items. When you press back, router ignores the event because the 'back' url matches the current router url. If you call location.go() twice and navigate back, the back url is http://localhost:4200/items;openedId=123 and doesn't match the router url, so paramMap is triggered.

    A workaround may be to add some unique param to the url, like current timestamp, I tried and it works, but it isn't the best solution definitely. I ended up using Route.navigate() instead of location.go(). If you want to filter some navigations, it's possible by passing state to the navigate method, afterwards you can filter navigations by accessing the state via Router.getCurrentNavigation().

    The problem is that the Location isn't designed for route changes, the service documentation tells:

    It's better to use the Router#navigate service to trigger route changes. Use Location only if you need to interact with or create normalized URLs outside of routing.