Angular 2 How to detect the back button using a router and location.go ()?

I created an application that uses router 3.0.0-beta.1 to switch between sections of the application. I also use location.go() to emulate a switch between sub-sections of the same page. I used <base href="/"> and some URL rewriting rules to redirect all routes to index.html in case of page refresh. This allows the router to receive the requested subkey as a URL parameter. I mostly managed to avoid using HashLocationStrategy .

routes.ts

 export const routes: RouterConfig = [ { path: '', redirectTo: '/catalog', pathMatch: 'full' }, { path: 'catalog', component: CatalogComponent }, { path: 'catalog/:topCategory', component: CatalogComponent }, { path: 'summary', component: SummaryComponent } ]; 

If I click on a subsection in the navigation bar 2, everything happens:

  • logation.go() updates the URL with the necessary string to indicate the current subkey
  • Custom animation scrollTo() scrolls the page at the top of the requested subkey.

If I refresh the page, I use the previously defined route and extract the necessary option to restore the scroll to the required subkey.

 this._activatedRoute.params .map(params => params['topCategory']) .subscribe(topCategory => { if (typeof topCategory !== 'undefined' && topCategory !== null ) { self.UiState.startArrowWasDismised = true; self.UiState.selectedTopCategory = topCategory; } }); 

Everything works fine, except when I click the back button. If the previous page was a different section, the application router behaves as expected. However, if the previous page / url was a subdivision, the url changes to the previous one, but nothing happens in the user interface. How to determine if the back button has been pressed to call scrollTo() to work again?

Most of the answers I've seen relate to the onhashchange event, but this event does not fire in my application since I don't have a hash in the url after ...

+12
source share
7 answers

I don't know if the answers are dated, but none of them helped me in the latest version of Angular. I added an Angular event handler by importing it into my component:

 import { HostListener } from '@angular/core'; 

and then listening to popstate on the window object (as Adrian recommended):

  @HostListener('window:popstate', ['$event']) onPopState(event) { console.log('Back button pressed'); } 

It worked for me.

+16
source

To find the back button, click the import platformlocation button from '@ angular / common and put the code below in your constructor:

  constructor(location: PlatformLocation) { location.onPopState(() => { alert(window.location); }); } 
+5
source

Angular documentation right in the PlatformLocation class ...

  • This class should not be used directly by the application developer.

I used LocationStrategy in the constructor

 constructor(location: LocationStrategy) { location.onPopState(() => { alert(window.location); }); } 
+5
source

I agree with Adrian Moys’ answer,

but you can use the “more Angular 2 way” method using the PlatformLocation class by introducing your component or service, then you can define the onPopState callback as follows:

 this.location.onPopState(()=>{ // your code here... this.logger.debug('onpopstate event'); }); 
+3
source

Another alternative for this problem would be to subscribe to events generated by the Angular Router service . Since we are dealing with routing, it seems to me that using router events makes more sense.

 constructor(router: Router) { router.events .subscribe((event: NavigationStart) => { if (event.navigationTrigger === 'popstate') { // Perform actions } }); } 

I would like to note that popstate happens when you click back and forth in the browser. Thus, in order to do this effectively, you will need to find a way to determine which one is happening. For me it was just using an event object of type NavigationStart , which gives information about where the user is coming from and where he is going to.

+3
source

A great clean way is to import fromEvent from rxjs and use it that way.

 fromEvent(window, 'popstate') .subscribe((e) => { console.log(e, 'back button'); }); 
+2
source

Using the onpopstate event got the trick:

 window.addEventListener('popstate', // Add your callback here () => self.events.scrollToTopCategory.emit({ categId: self.state.selectedTopCategory }) ); 
+1
source

All Articles