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?
This question is related to
angular
angular2-routing
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.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.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);
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
.
Since beta 18:
import {Location} from 'angular2/platform/common';
Another solution
window.history.back();
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;
}
}
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>
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>
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>
<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>
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();
}
}
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
}
}
In RC4:
import {Location} from '@angular/common';
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
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.
Source: Stackoverflow.com