3

Going back to the previous page in Angular is fairly simple:

import {Component} from '@angular/core';
import {Location} from '@angular/common';

@Component({
  // component's declarations here
})
class SomeComponent {

  constructor(private _location: Location) 
  {}

  backClicked() {
    this._location.back();
  }
}

This is the equivalent of hitting your browser's "back" button. But how can this code be modified such that if this._location.back() is going to take you to a url outside of the app, that it instead redirects you to a route inside the app.

For example, say you're at Google.com and then you paste in my-app.com/page-foo and navigate that way. this._location.back() will take you back to Google.com, but I want it to instead navigate to my-app.com/page-bar.

tgordon18
  • 1,562
  • 1
  • 19
  • 31
  • According to the [docs](https://angular.io/api/common/Location#usage-notes), in your case you should use **router.navigate** method – vitaliy kotov Nov 25 '20 at 13:45
  • Does that have a way of going `back` though? – tgordon18 Nov 25 '20 at 13:51
  • you have to provide the url to which navigation should be done. usually this url is known, if it's not generic solution and you call it in component on some user's action – vitaliy kotov Nov 25 '20 at 13:55
  • Right but the primary action that I want is to go `back`. With `location.back()` you don't need to know the url to use it. If I want to use `router.navigate` as you said, I would need some way of knowing what the previous url was – tgordon18 Nov 25 '20 at 13:56

1 Answers1

1

Found the answer at https://nils-mehlhorn.de/posts/angular-navigate-back-previous-page.

1. Make a new navigation-service:

import { Injectable } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { Location } from '@angular/common';

@Injectable({
  providedIn: 'root'
})
export class NavigationService {
  private MAX_HISTORY_LEN = 10; // prevent history from growing indefinitely
  private history: string[] = [];

  constructor(private router: Router, private location: Location) {
    this.router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
        this.history.push(event.urlAfterRedirects);
        if (this.history.length > this.MAX_HISTORY_LEN) {
          this.history.shift();
        }
      }
    });
  }

  back(): void {
    this.history.pop();
    if (this.history.length > 0) {
      this.location.back();
    } else {
      this.router.navigateByUrl('/');
    }
  }
}

2. Inject the service into app.component.ts so that it tracks history throughout the application

export class AppComponent implements AfterViewInit {

  constructor(private navigationService: NavigationService) {
  }
  ...

3. Then update the (click) function wherever you want to use this. Using the original example:

@Component({
  // component's declarations here
})
class SomeComponent {

  constructor(private navigationService: NavigationService) 
  {}

  backClicked() {
    this.navigationService.back();
  }
}

I made a few adjustments from the blogpost:

  • Added a MAX_HISTORY_LEN to prevent the history array from growing indefinitely throughout app use
  • Injected the navigation-service in app.component.ts so that it's always tracking history. If you only inject the service in the component that's calling .back() then it might not have a history the first time you call it.
tgordon18
  • 1,562
  • 1
  • 19
  • 31