How to go back last page

AngularAngular2 Routing

Angular Problem Overview


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?

Angular Solutions


Solution 1 - Angular

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.

Solution 2 - Angular

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
  }
}

Solution 3 - Angular

<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>

Solution 4 - Angular

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>

Solution 5 - Angular

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

Solution 6 - Angular

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

Solution 7 - Angular

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>

Solution 8 - Angular

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.

Solution 9 - Angular

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.

Solution 10 - Angular

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.

Solution 11 - Angular

In RC4:

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

Solution 12 - Angular

Since beta 18:

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

Solution 13 - Angular

> 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>

Solution 14 - Angular

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

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

and

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

Solution 15 - Angular

Another solution

window.history.back();

Solution 16 - Angular

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
  }
}

Solution 17 - Angular

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

Solution 18 - Angular

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

Solution 19 - Angular

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

Solution 20 - Angular

try routerLink="../child"

Solution 21 - Angular

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHongbo MiaoView Question on Stackoverflow
Solution 1 - AngularAmir SassonView Answer on Stackoverflow
Solution 2 - AngularHinrichView Answer on Stackoverflow
Solution 3 - AngularhansmaadView Answer on Stackoverflow
Solution 4 - AngularJavierFuentesView Answer on Stackoverflow
Solution 5 - AngularSasxaView Answer on Stackoverflow
Solution 6 - AngularAnjil DhamalaView Answer on Stackoverflow
Solution 7 - AngularShevtsiv AndriyView Answer on Stackoverflow
Solution 8 - AngularTodd SkeltonView Answer on Stackoverflow
Solution 9 - AngularPuneeth RaiView Answer on Stackoverflow
Solution 10 - AngularParziphalView Answer on Stackoverflow
Solution 11 - AngularTomasz BielawaView Answer on Stackoverflow
Solution 12 - AngularAlbertView Answer on Stackoverflow
Solution 13 - AngularSinghakView Answer on Stackoverflow
Solution 14 - AngularjprismView Answer on Stackoverflow
Solution 15 - AngularDžan OpertaView Answer on Stackoverflow
Solution 16 - AngularNaeem BashirView Answer on Stackoverflow
Solution 17 - AngularCarlos AlbertoView Answer on Stackoverflow
Solution 18 - AngularMohammad RezaView Answer on Stackoverflow
Solution 19 - AngularYuriy GyertsView Answer on Stackoverflow
Solution 20 - AngularRojin GharooniView Answer on Stackoverflow
Solution 21 - AngularGal MargalitView Answer on Stackoverflow