575

Is there a smart way to go back last page in Angular 2?

Something like

this._router.navigate(LASTPAGE);

For example, page C has a Go Back button,

  • Page A -> Page C, click it, back to page A.

  • Page B -> Page C, click it, back to page B.

Does router have this history information?

Hongbo Miao
  • 45,290
  • 60
  • 174
  • 267

29 Answers29

1025

Actually you can take advantage of the built-in Location service, which owns a "Back" API.

Here (in TypeScript):

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();
  }
}

Edit: As mentioned by @charith.arumapperuma Location should be imported from @angular/common so the import {Location} from '@angular/common'; line is important.

Kishan Vaishnav
  • 2,273
  • 1
  • 17
  • 45
Amir Sasson
  • 10,985
  • 1
  • 13
  • 25
  • There is no built in back in the location service – Justin May 01 '16 at 05:23
  • hi Justin, please refer to https://angular.io/docs/js/latest/api/router/Location-class.html#!#back-anchor you would see the angular 2 documentation and see that there is a "Built in" back() – Amir Sasson May 06 '16 at 12:39
  • 96
    The Location should be imported from "angular2/router" in older releases of Angular 2. In newer releases, it should be from "@angular/common". – charith.arumapperuma May 12 '16 at 14:37
  • Is it correct to assert: never use "window.history.back();" in Angular 2? – Johannes Jul 21 '16 at 10:00
  • 3
    If you have it built in in the framework, I dont see any reason to use the "native" "window.history.back();" which is an HTML5 feature (https://developer.mozilla.org/en-US/docs/Web/API/Window/history) – Amir Sasson Jul 21 '16 at 13:55
  • 10
    For what it's worth, the official Angular2 API documentation for `Location` states: "Note: it's better to use Router service to trigger route changes. Use Location only if you need to interact with or create normalized URLs outside of routing." [@Sasxa's answer](http://stackoverflow.com/a/35447012/5218951) does apparently show a way to use `Router` to do this. However, the `Location` method definitely is more convenient. Does anyone know why the `Router` method might be more correct than the `Location` method? – Andrew Willems Sep 16 '16 at 14:50
  • 2
    @Andrew: I've encountered the problem, that you cannot go back two times, if you use this.location.back(). You will jump back to the initial site. – Johannes Sep 19 '16 at 11:15
  • How would I do a conditional navigation? let's say I am in an article details page... but an error happens... and I have a buttons saying "error happened, cklick to go back to article list" now, if the previous URL was article list I want to use this._location.back().... if not, I want to use router.navigate(['articleList']); – DS_web_developer Dec 06 '16 at 15:56
  • @DS_web_developer, i think there is not other way but to pragmatically implement what you just described in the Button click handler. like: if(error) then navigate to X, otherwise location.back(). will this be good for you? – Amir Sasson Dec 06 '16 at 16:09
  • not really... this button is displaying JUST on error.... and I need on the click: if(this.router.previous.has('articleList')){location.back();}else{router.navigate(['/articleList']);} ... The point being, that the previous URL (if coming from article list) might have URL parameters (like filters, pagination, sorting, etc)... and I want the page to go back to that if it's set.... but if a user just navigates to the article from outside source and not via the list (or maybe from a homepage widget) than redirect him to the root of the articleList – DS_web_developer Dec 06 '16 at 16:31
  • Is there any disadvantege of this solution instead of preparing routerLink? – TomOw May 15 '17 at 13:40
  • 1
    @yt61, not sure, maybe re-usability? or if you can get to a specified page from various routes, so you dont know in advance the route to go back to. – Amir Sasson May 16 '17 at 07:07
  • There is some bloat/unneeded code in this answer, Hinrich's answer below is the same yet more elegant – astro8891 Jun 14 '17 at 22:23
  • When I use `this._location.back()` I get some component null error, which don't happen on using `window.history.back()`. So maybe it's better to use history.back instead of Location.back? – Sam Aug 08 '17 at 11:50
  • 1
    Using the router method would run the resolvers again @AndrewWillems – Zymotik Aug 23 '17 at 12:21
  • @Johannes Not having this issue on v4.4.4. Was this on an older version? – mhodges Jan 22 '18 at 18:46
  • If you use an **anchor instead of a button** you will need make it a **passive link** like this `Back` ... as you can see in [this response](https://stackoverflow.com/a/49596797/7120290). – JavierFuentes Apr 01 '18 at 09:49
  • how is backClicked() tied to the event?, this function will not run for me. – Andrew Daly May 15 '19 at 10:52
145

In the final version of Angular 2.x / 4.x - here's the docs https://angular.io/api/common/Location

/* typescript */

import { Location } from '@angular/common';
// import stuff here

@Component({
// declare component here
})
export class MyComponent {

  // inject location into component constructor
  constructor(private location: Location) { }

  cancel() {
    this.location.back(); // <-- go back to previous location on cancel
  }
}
Daniel Gray
  • 1,697
  • 1
  • 21
  • 41
Hinrich
  • 13,485
  • 7
  • 43
  • 66
102

<button backButton>BACK</button>

You can put this into a directive, that can be attached to any clickable element:

import { Directive, HostListener } from '@angular/core';
import { Location } from '@angular/common';

@Directive({
    selector: '[backButton]'
})
export class BackButtonDirective {
    constructor(private location: Location) { }

    @HostListener('click')
    onClick() {
        this.location.back();
    }
}

Usage:

<button backButton>BACK</button>
BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
hansmaad
  • 18,417
  • 9
  • 53
  • 94
  • that's awesome! – Rafael de Castro Dec 02 '19 at 14:54
  • 4
    If you refresh on this page, and click on the button that triggers "this.location.back()", it will just trigger a page refresh. Is there any way that the Location module can detect if previous path exists? – Henry Jan 09 '20 at 02:27
  • 1
    Keep in mind if a user went directly to a page where Back button exists and if he clicks on a button.. then he will be throw out of the app to the previous page according to the browser(platform) history. – hastrb Apr 24 '20 at 08:23
  • For future readers, look at [API docs](https://angular.io/api/common/Location#back) – hastrb Apr 24 '20 at 08:30
  • awesome solution thanks. – Caner Dec 19 '21 at 01:16
  • I had to add BackButtonDirective in the declarations list in app.module.ts to make it work. – Asaf M Mar 24 '23 at 14:38
31

Tested with Angular 5.2.9

If you use an anchor instead of a button you must make it a passive link with href="javascript:void(0)" to make Angular Location work.

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent {

  constructor( private location: Location ) { 
  }

  goBack() {
    // window.history.back();
    this.location.back();

    console.log( 'goBack()...' );
  }
}

app.component.html

<!-- anchor must be a passive link -->
<a href="javascript:void(0)" (click)="goBack()">
  <-Back
</a>
JavierFuentes
  • 1,840
  • 18
  • 13
  • I would suggest creating a 'clickPreventDefault' directive rather than using `javascript:void(0)`. Something like... `@Directive({ selector: '[clickPreventDefault]' }) export class ClickPreventDefaultDirective { @HostListener("click", ["$event"]) onClick($event: Event) { $event.preventDefault(); } }` – bmd Apr 10 '18 at 10:22
  • Thank you @bmd , it's a more elaborate way but it works too. Another working solution is don't use herf: although this way don't pass HTML Validators. – JavierFuentes Apr 12 '18 at 08:59
20

You can implement routerOnActivate() method on your route class, it will provide information about previous route.

routerOnActivate(nextInstruction: ComponentInstruction, prevInstruction: ComponentInstruction) : any

Then you can use router.navigateByUrl() and pass data generated from ComponentInstruction. For example:

this._router.navigateByUrl(prevInstruction.urlPath);
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Sasxa
  • 40,334
  • 16
  • 88
  • 102
20

Maybe you'd like to check if the previous point of history is within your app. For example, if you enter directly to your app and do location.back() (by pressing a <- back button in a toolbar for example), you'd be back to your browser's main page, instead of going somewhere else within your app.

This is how I check for this:

import { Component } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Location } from '@angular/common';

@Component({
  selector: 'app-foo',
  template: ''
})
export class FooComponent {

  private readonly canGoBack: boolean;

  constructor(
    private readonly route: ActivatedRoute,
    private readonly router: Router,
    private readonly location: Location
  ) {
    // This is where the check is done. Make sure to do this
    // here in the constructor, otherwise `getCurrentNavigation()`
    // will return null. 
    this.canGoBack = !!(this.router.getCurrentNavigation()?.previousNavigation);
  }

  goBack(): void {
    if (this.canGoBack) {
      // We can safely go back to the previous location as
      // we know it's within our app.
      this.location.back();
    } else {
      // There's no previous navigation.
      // Here we decide where to go. For example, let's say the
      // upper level is the index page, so we go up one level.
      this.router.navigate(['..'], {relativeTo: this.route});
    }
  }

}

We check if the navigation that loaded the current route has a previous sibling. This has to be done in the constructor, while the navigation process is still active.

This doesn't come without caveats though:

  • canGoBack will be false even if the previous location is actually within our app but the page was refreshed.
  • The user might want to "go back" to the previous page (where the goBack() ocurred) by clicking the browser's back button, but since the app went back on history instead of pushing a new location, the user will be going back even further and might get confused.
Parziphal
  • 6,222
  • 4
  • 34
  • 36
18

After all these awesome answers, I hope my answer finds someone and helps them out. I wrote a small service to keep track of route history. Here it goes.

import { Injectable } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { filter } from 'rxjs/operators';

@Injectable()
export class RouteInterceptorService {
  private _previousUrl: string;
  private _currentUrl: string;
  private _routeHistory: string[];

  constructor(router: Router) {
    this._routeHistory = [];
    router.events
      .pipe(filter(event => event instanceof NavigationEnd))
      .subscribe((event: NavigationEnd) => {
        this._setURLs(event);
      });
  }

  private _setURLs(event: NavigationEnd): void {
    const tempUrl = this._currentUrl;
    this._previousUrl = tempUrl;
    this._currentUrl = event.urlAfterRedirects;
    this._routeHistory.push(event.urlAfterRedirects);
  }

  get previousUrl(): string {
    return this._previousUrl;
  }

  get currentUrl(): string {
    return this._currentUrl;
  }

  get routeHistory(): string[] {
    return this._routeHistory;
  }
}
Anjil Dhamala
  • 1,544
  • 3
  • 18
  • 37
  • After trying more or less all solutions, I find this one is the more consistent way to do that – A. D'Alfonso Mar 27 '19 at 16:44
  • What if I open the page on particular link and I want that it will go back to page that in page tree? – Ivan Feb 11 '20 at 08:45
  • Iḿ getting error Type string has no call signatures when calling preiousUrl(). Can you help me out? :D – Lorand Jul 27 '20 at 09:50
  • @SzokeLori Sounds like your "this" is pointing to String type. You should post a question with the code. – Anjil Dhamala Jul 27 '20 at 14:03
  • @AnjilDhamala well... i just injected the thing as private to constructor and wanted to console log it. Mind me, im a beginner – Lorand Jul 27 '20 at 16:47
  • @SzokeLori: I understand. However, it's hard to tell what exactly is going wrong in your context. Did you register this injectable in a Module? If possible, post your question in this website and put a link in this comment section. I'll try to help you out if someone hasn't already. – Anjil Dhamala Jul 27 '20 at 17:40
17

Also work for me when I need to move back as in file system. P.S. @angular: "^5.0.0"

<button type="button" class="btn btn-primary" routerLink="../">Back</button>
Shevtsiv Andriy
  • 215
  • 2
  • 3
  • 10
    I was hopeful this would work, but this moves back to the next Route above it - not to the route you were on before navigating to the page. Good to know this exists, but if you have multiple entry points for your component, this method will only ever go back to the route above it, not where you originated from. – Scott Byers Jan 09 '18 at 22:44
  • As I write "when I need to move back as in file system" :) For me, this behavior was also unexpected. – Shevtsiv Andriy Jan 23 '18 at 13:39
  • 1
    You're confusing *back* (e.g. `cd -`) with *up* (`cd ..`). Nevertheless, it's handy to know this works. – devios1 Jan 26 '21 at 14:41
  • This returns to the parent view (it does not always equate to the previous view) – morrigannn Feb 01 '22 at 13:35
16

I made a button I can reuse anywhere on my app.

Create this component

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

@Component({
    selector: 'back-button',
    template: `<button mat-button (click)="goBack()" [color]="color">Back</button>`,
})
export class BackButtonComponent {
    @Input()color: string;

  constructor(private location: Location) { }

  goBack() {
    this.location.back();
  }
}

Then add it to any template when you need a back button.

<back-button color="primary"></back-button>

Note: This is using Angular Material, if you aren't using that library then remove the mat-button and color.

Todd Skelton
  • 6,839
  • 3
  • 36
  • 48
  • Does this approach work with named router outlets though? Say I have several on the page and only want to go back on one of them, would this work? – rrd Feb 09 '18 at 10:25
  • You'll have to use a different approach for that situation. If you had the same back button in two different router outlets, they will probably both do the same thing and go back on the last router outlet that was changed. – Todd Skelton Feb 14 '18 at 23:00
  • For named outlets, I found that this approach worked: this.router.navigate(['../'], {relativeTo: this.route}) – rrd Feb 15 '18 at 08:11
  • How to use this component inside another component? – RN Kushwaha May 29 '19 at 12:21
11

The way I did it while navigating to different page add a query param by passing current location

this.router.navigate(["user/edit"], { queryParams: { returnUrl: this.router.url }

Read this query param in your component

this.router.queryParams.subscribe((params) => {
    this.returnUrl = params.returnUrl;
});

If returnUrl is present enable the back button and when user clicks the back button

this.router.navigateByUrl(this.returnUrl); // Hint taken from Sasxa

This should able to navigate to previous page. Instead of using location.back I feel the above method is more safe consider the case where user directly lands to your page and if he presses the back button with location.back it will redirects user to previous page which will not be your web page.

Puneeth Rai
  • 1,163
  • 10
  • 11
  • Need to import ActivatedRoute and use that instead of Router on the queryParams subscription (e.g., this.route.queryParams.subscribe), but otherwise, seems to work! – Stephen Kaiser Jun 13 '17 at 23:12
  • for me it is working fine with router itself even in angular 4 – Puneeth Rai Jun 15 '17 at 10:53
  • 1
    Best answer, but in Angular 5 (up to x?) you need to inject an object of "ActivatedRoute" and use queryParams on this object, as Stephen Kaiser already stated. – Satria Jan 10 '20 at 12:54
11

Simply use Location , An Angular service that applications can use to interact with a browser's URL.

Import it :

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

Inject it :

constructor(private location: Location) { }

Simply Use it :

goBack() {
    this.location.back(); // Navigates back in the platform's history
}
Sangwin Gawande
  • 7,658
  • 8
  • 48
  • 66
  • 2
    Beware that there's an edge case with this scenario such that if user opens a new tab there won't be an entry in the history to go back to. This can throw user out of the Angular application as well as introduce security issues as there's no API for directly inspecting the browser history. – Ali Celebi Oct 25 '22 at 13:21
6

In RC4:

import {Location} from '@angular/common';
Derlin
  • 9,572
  • 2
  • 32
  • 53
Tomasz Bielawa
  • 125
  • 1
  • 3
4

Another solution

window.history.back();

Džan Operta
  • 399
  • 2
  • 11
4

To go back without refreshing the page, We can do in html like below javascript:history.back()

<a class="btn btn-danger" href="javascript:history.back()">Go Back</a>
Singhak
  • 8,508
  • 2
  • 31
  • 34
  • 1
    I would recommend using `Location` service instead. [official API](https://angular.io/api/common/Location#back) – hastrb Apr 24 '20 at 08:29
4

Please make sure you explicitly import if you are using latest Angular/TypeScript

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

and

 onCancel() {
    this.location.back();
  }
jprism
  • 3,239
  • 3
  • 40
  • 56
  • 1
    just unfortunate that the answer was already given 5 years earlier, and even misses the part where you define `location` in the constructor – bvdb May 16 '22 at 11:41
  • Yes, don't forget to define in your constructor() the: private location: Location – Dylan Moguilevsky Jun 03 '22 at 17:55
  • As noted above for one of the proposed solutions, beware that there's an edge case with this scenario such that if user opens a new tab there won't be an entry in the history to go back to. This can throw user out of the Angular application as well as introduce security issues as there's no API for directly inspecting the browser history. – Ali Celebi Oct 25 '22 at 13:22
3

Since beta 18:

import {Location} from 'angular2/platform/common';

Albert
  • 107
  • 1
  • 4
3

2022
Utilize your app routing - more of an "angular approach" rather than accessing the browser's location object for navigation history. Think of why you need the user to go 'back', and what 'back' means in the broader context of your application and its routes.

for example, returning to a parent route from its child

  this.router.navigate(['..'], {relativeTo: this.route});

You can also read about previous navigation

previousNavigation : The previously successful Navigation object. Only one previous navigation is available, therefore this previous Navigation object has a null value for its own previousNavigation.

Gal Margalit
  • 5,525
  • 6
  • 52
  • 56
2

in angular 4 use preserveQueryParams, ex:

url: /list?page=1

<a [routerLink]="['edit',id]" [preserveQueryParams]="true"></a>

When clicking the link, you are redirected edit/10?page=1, preserving params

ref: https://angular.io/docs/ts/latest/guide/router.html#!#link-parameters-array

Derlin
  • 9,572
  • 2
  • 32
  • 53
2

im using this way:

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

@Component({
    selector: 'Back_page',
    template: `<button  (click)="onBack()">Back</button>`,
})
export class BackPageComponent {
  constructor(private location: Location) { }

  onBack() {
    this.location.back();// <-- go back to previous location
  }
}
Naeem Bashir
  • 1,937
  • 20
  • 17
2

I came up with this, you can also check if there is a previous page. Make sure to use the service in your appComponent.

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

interface HistoryData {
  previousPage: string | null,
  currentPage: string | null,
}

@Injectable({ providedIn: 'root' })
export class GoBackService {

  private historyData: HistoryData = { previousPage: null, currentPage: null };

  constructor(private router: Router, private location: Location) {
    this.router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
        this.historyData.previousPage = this.historyData.currentPage;
        this.historyData.currentPage = event.urlAfterRedirects;
      }
    });
  }

  public goBack(): void {
    if (this.historyData.previousPage) this.location.back();
  }

  public canGoBack(): boolean {
    return Boolean(this.historyData.previousPage);
  }

}
Niels Prins
  • 535
  • 2
  • 11
2

Imports:

import { Location } from '@angular/common';
import { Router } from '@angular/router';

Constructor:

constructor(private readonly router: Router, private readonly location: Location) {
  location.onUrlChange(() => this.canGoBack = !!this.router.getCurrentNavigation()?.previousNavigation);
}

Optional, avoiding to go back outside the application:

private canGoBack: boolean = false;

constructor(private router:Router,private location:Location){
  this.canGoBack = !!(this.router.getCurrentNavigation()?.previousNavigation);
}

Go back:

goBack(): void {
  if (this.canGoBack) {
    this.location.back();
  }
}

Html:

<button (click)="goBack()"></button>
danilo
  • 7,680
  • 7
  • 43
  • 46
1

yes you can do it. write this code on your typescript component and enjoy!

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

@Component({
    selector: 'return_page',
    template: `<button mat-button (click)="onReturn()">Back</button>`,
})
export class ReturnPageComponent {
  constructor(private location: Location) { }

  onReturn() {
    this.location.back();
  }
}
1

If you wanna go back to the previous Window, You can use History API.

window.history.back();

Note: This API is only available on the main thread (Window). It cannot be accessed in Worker or Worklet contexts.

0

Also you can use this service with fallback feature in case history is empty

url-back.service.ts

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

import { Router } from '@angular/router';

const EMPTY_HISTORY_LENGTH = 2;

/**
 * This service helps to Navigate back to the prev page, and if no prev page,
 * will redirect to the fallback url.
 */
@Injectable()
export class UrlBackService {
  constructor(private router: Router, private location: Location) {}

  /**
   * This method will back you to the previous page,
   * if no previous page exists, will redirect you to the fallback url.
   * @param href - url, if tryNativeFirst is provided, this is fallback url
   * @param tryNativeFirst - try to go back natively using browser history state.
   */
  back(href: string, tryNativeFirst: boolean = false) {
    if (tryNativeFirst) {
      if (history.length === EMPTY_HISTORY_LENGTH) {
        this.router.navigate(UrlBackService.urlToArray(href));
      } else {
        this.location.back();
      }
    } else {
      this.router.navigate(UrlBackService.urlToArray(href));
    }
  }

  /**
   * In case that router.navigate method tries to escape all '/' in the string,
   * was decided to split string to array, and if URL starts or ends with slash - remove them, eg:
   * /my/url will be split to ['', 'my', 'url'], so we need to remove empty spaces use filter function.
   * @param href
   * @private
   */
  private static urlToArray(href: string) {
    return href.split('/').filter((notEmpty) => notEmpty);
  }
}

url-back.service.spec.ts

import { TestBed } from '@angular/core/testing';

import { UrlBackService } from './url-back.service';
import { Router } from '@angular/router';
import { Location } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';

describe('UrlBackService', () => {
  let service: UrlBackService;
  let router: Router;
  let location: Location;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule],
      providers: [UrlBackService],
    });
    service = TestBed.inject(UrlBackService);
    router = TestBed.inject(Router);
    location = TestBed.inject(Location);
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });

  it('no meter what history state is, it should be redirected to the /my/url', () => {
    spyOn(router, 'navigate');
    service.back('/my/url');
    expect(router.navigate).toHaveBeenCalledWith(['my', 'url']);
  });

  it('in case history is empty push to /my/url', () => {
    spyOn(router, 'navigate');
    service.back('/my/url', true);
    expect(router.navigate).toHaveBeenCalledWith(['my', 'url']);
  });

  it('in case history is NOT empty push to url1', () => {
    spyOn(location, 'back');
    window.history.pushState(null, '', 'url1');

    service.back('/my/url', true);
    expect(location.back).toHaveBeenCalled();
  });
});
Yuriy Gyerts
  • 1,464
  • 18
  • 30
0

try routerLink="../LASTPAGE"

0

Version of @Parziphal answer for non-change detected components:

  import { Location } from '@angular/common';
  import { Router } from '@angular/router';

  constructor(private readonly router: Router, private readonly location: Location) {
    location.onUrlChange(() => this.canGoBack = !!this.router.getCurrentNavigation()?.previousNavigation);
  }

  goBack(): void {
    if (this.canGoBack) {
      this.location.back();
    }
  }

danilo
  • 7,680
  • 7
  • 43
  • 46
kudko
  • 1
  • 1
0

The latest update from Angular 14. If previousUrl is undefined we will route to the predefined previous URL.

import { Location } from '@angular/common';
import { filter, Subject, takeUntil } from 'rxjs';
import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';

private previousUrl: string;
private ngUnsubscribe: Subject<any> = new Subject<any>();

constructor(
    private router: Router,
    private activatedRoute: ActivatedRoute,
    private location: Location
) {
    router.events
        .pipe(
            takeUntil(this.ngUnsubscribe),
            filter((event) => event instanceof NavigationEnd)
        )
        .subscribe((event: NavigationEnd) => {
            this.previousUrl = event.url;
        });
}

public async goBack() : Promise<void> {
   if (this.previousUrl) {
     this.location.back();
   } else {
     await this.router.navigate(['..'], {
         relativeTo: this.activatedRoute,
     });
   }
}

ngOnDestroy(): void {
    this.ngUnsubscribe.next(true);
    this.ngUnsubscribe.complete();
}
Tang Thanh Tam
  • 431
  • 3
  • 12
0

you could use the ngx-back-button library, which also take care

  1. of the browser history

  2. If you first land on the back and directly click on the back button

  3. run `npm install ngx-back-button``

  4. Inside your app.module.ts file.

import { NgxBackButtonModule, NgxBackButtonService } from 'ngx-back-button'

  imports: [
    NgxBackButtonModule.forRoot()
  ],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: () => () => null,
      deps: [NgxBackButtonService],
      multi: true,
    },
  ]
  1. Then
// foo.component.ts
import { NgxBackButtonService } from 'ngx-back-button'

// ...
 constructor(public ngxBackButtonService: NgxBackButtonService) {}

 back() {
   ngxBackButtonService.back()
 }
  1. Or with a directive
<button ngxBackButton>
  Back
</button>
Raphaël Balet
  • 6,334
  • 6
  • 41
  • 78
0

As many of the answers don't take into account all the aspects of back navigation,
I've created a little library that does the trick.

It handles

  1. Browser history
  2. Fallback when clicking on the back button when not routed yet
  3. Customized fallback

Installation

npm install ngx-back-button

import { NgxBackButtonModule, NgxBackButtonService } from 'ngx-back-button'

  imports: [
    NgxBackButtonModule.forRoot(), // Default rootUrl === '/'

    // Or
    NgxBackButtonModule.forRoot({
      rootUrl: '/custom', // Or any custom root url
      fallbackPrefix: '/tabs' // For libraries users
    }),
  ],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: () => () => null,
      deps: [NgxBackButtonService],
      multi: true,
    },
  ]

Then where you need to navigate back

// foo.component.ts
import { NgxBackButtonService } from 'ngx-back-button'

// ...
 constructor(public ngxBackButtonService: NgxBackButtonService) {}

 navigateBack() {
  this.ngxBackButtonService.back()
 }
Raphaël Balet
  • 6,334
  • 6
  • 41
  • 78