How to determine previous page URL in Angular?

AngularAngular2 Routing

Angular Problem Overview


Suppose I am currently on the page which has the URL /user/:id . Now from this page I navigate to next page :id/posts.

Now Is there a way, so that i can check what is the previous URL, i.e. /user/:id.

Below are my routes

export const routes: Routes = [
  { 
	path: 'user/:id', component: UserProfileComponent
  },
  {  
    path: ':id/posts', component: UserPostsComponet 
  }
];

Angular Solutions


Solution 1 - Angular

Maybe all other answers are for angular 2.X.

Now it doesn't work for angular 5.X. I'm working with it.

with only NavigationEnd, you can not get previous url.

because Router works from "NavigationStart", "RoutesRecognized",..., to "NavigationEnd".

You can check with

router.events.forEach((event) => {
  console.log(event);
});

But still you can not get previous url even with "NavigationStart".

Now you need to use pairwise.

import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/pairwise';

constructor(private router: Router) {
  this.router.events
    .filter(e => e instanceof RoutesRecognized)
    .pairwise()
    .subscribe((event: any[]) => {
      console.log(event[0].urlAfterRedirects);
    });
}
    

With pairwise, You can see what url is from and to.

"RoutesRecognized" is the changing step from origin to target url.

so filter it and get previous url from it.

Last but not least,

put this code in parent component or higher (ex, app.component.ts)

because this code fires after finish routing.

Update angular 6+

The events.filter gives error because filter is not part of events, so change the code to

import { filter, pairwise } from 'rxjs/operators';

this.router.events
.pipe(filter((evt: any) => evt instanceof RoutesRecognized), pairwise())
.subscribe((events: RoutesRecognized[]) => {
  console.log('previous url', events[0].urlAfterRedirects);
  console.log('current url', events[1].urlAfterRedirects);
});

Solution 2 - Angular

You can subscribe to route changes and store the current event so you can use it when the next happens

previousUrl: string;
constructor(router: Router) {
  router.events
  .pipe(filter(event => event instanceof NavigationEnd))
  .subscribe((event: NavigationEnd) => {
    console.log('prev:', event.url);
    this.previousUrl = event.url;
  });
}

See also https://stackoverflow.com/questions/33520043/how-to-detect-route-change-in-angular-2/38080657#38080657

Solution 3 - Angular

Create a injectable service:

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

 /** A router wrapper, adding extra functions. */
@Injectable()
export class RouterExtService {
  
  private previousUrl: string = undefined;
  private currentUrl: string = undefined;

  constructor(private router : Router) {
    this.currentUrl = this.router.url;
    router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        this.previousUrl = this.currentUrl;
        this.currentUrl = event.url;
      };
    });
  }

  public getPreviousUrl(){
    return this.previousUrl;
  }    
}

Then use it everywhere you need. To store the current variable as soon as possible, it's necessary to use the service in the AppModule.

// AppModule
export class AppModule {
  constructor(private routerExtService: RouterExtService){}

  //...

}

// Using in SomeComponent
export class SomeComponent implements OnInit {
  
  constructor(private routerExtService: RouterExtService, private location: Location) { } 

  public back(): void {
    this.location.back();
  }

  //Strange name, but it makes sense. Behind the scenes, we are pushing to history the previous url
  public goToPrevious(): void {
    let previous = this.routerExtService.getPreviousUrl();
    
    if(previous)
      this.routerExtService.router.navigateByUrl(previous);
  }

  //...

}

Solution 4 - Angular

Angular 6 updated code for getting previous url as string.

import { Router, RoutesRecognized } from '@angular/router';
import { filter, pairwise } from 'rxjs/operators';


export class AppComponent implements OnInit {
    
  constructor (
    public router: Router
  ) { }
    
  ngOnInit() {
    this.router.events
      .pipe(filter((e: any) => e instanceof RoutesRecognized),
        pairwise()
      ).subscribe((e: any) => {
    console.log(e[0].urlAfterRedirects); // previous url
  });
}

Solution 5 - Angular

Angular 8 & rxjs 6 in 2019 version

I would like to share the solution based on others great solutions.

First make a service to listen for routes changes and save the last previous route in a Behavior Subject, then provide this service in the main app.component in constructor then use this service to get the previous route you want when ever you want.

use case: you want to redirect the user to an advertise page then auto redirect him/her to where he did came from so you need the last previous route to do so.

// service : route-events.service.ts

import { Injectable } from '@angular/core';
import { Router, RoutesRecognized } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import { filter, pairwise } from 'rxjs/operators';
import { Location } from '@angular/common';

@Injectable()
export class RouteEventsService {

	// save the previous route
  public previousRoutePath = new BehaviorSubject<string>('');

  constructor(
  	private router: Router,
  	private location: Location
  ) {

  	// ..initial prvious route will be the current path for now
  	this.previousRoutePath.next(this.location.path());


  	// on every route change take the two events of two routes changed(using pairwise)
  	// and save the old one in a behavious subject to access it in another component
  	// we can use if another component like intro-advertise need the previous route
  	// because he need to redirect the user to where he did came from.
  	this.router.events.pipe(
  	  filter(e => e instanceof RoutesRecognized),
  	  pairwise(),
		)
  	.subscribe((event: any[]) => {
  	    this.previousRoutePath.next(event[0].urlAfterRedirects);
  	});

  }
}

provide the service in app.module

  providers: [
    ....
    RouteEventsService,
    ....
  ]

Inject it in app.component

  constructor(
    private routeEventsService: RouteEventsService
  )

finally use the saved previous route in the component you want

  onSkipHandler(){
    // navigate the user to where he did came from
  	this.router.navigate([this.routeEventsService.previousRoutePath.value]);
  }

Solution 6 - Angular

This worked for me in angular >= 6.x versions:

this.router.events
            .subscribe((event) => {
              if (event instanceof NavigationStart) {
                window.localStorage.setItem('previousUrl', this.router.url);
              }
            });

Solution 7 - Angular

FOR ANGULAR 7+

Actually since Angular 7.2 there is not need to use a service for saving the previous url. You could just use the state object to set the last url before linking to the login page. Here is an example for a login scenario.

@Component({ ... })
class SomePageComponent {
  constructor(private router: Router) {}

  checkLogin() {
    if (!this.auth.loggedIn()) {
      this.router.navigate(['login'], { state: { redirect: this.router.url } });
    }
  }
}
@Component({...})
class LoginComponent {
  constructor(private router: Router) {}

  backToPreviousPage() {
    const { redirect } = window.history.state;

    this.router.navigateByUrl(redirect || '/homepage');
  }
}


Additionally you could also pass the data in the template:

@Component({
  template: '<a routerLink="/some-route" [state]="{ redirect: router.url}">Go to some route</a>'
})
class SomePageComponent {
  constructor(public router: Router) {}
}

Solution 8 - Angular

I'm using Angular 8 and the answer of @franklin-pious solves the problem. In my case, get the previous url inside a subscribe cause some side effects if it's attached with some data in the view.

The workaround I used was to send the previous url as an optional parameter in the route navigation.

this.router.navigate(['/my-previous-route', {previousUrl: 'my-current-route'}])

And to get this value in the component:

this.route.snapshot.paramMap.get('previousUrl')

this.router and this.route are injected inside the constructor of each component and are imported as @angular/router members.

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

Solution 9 - Angular

@GünterZöchbauer also you can save it in localstorage but I not prefer it ) better to save in service and get this value from there

 constructor(
        private router: Router
      ) {
        this.router.events
          .subscribe((event) => {
            if (event instanceof NavigationEnd) {
              localStorage.setItem('previousUrl', event.url);
            }
          });
      }

Solution 10 - Angular

You can use Location as mentioned here.

Here's my code if the link opened on new tab

navBack() {
    let cur_path = this.location.path();
    this.location.back();
    if (cur_path === this.location.path())
     this.router.navigate(['/default-route']);    
  }

Required imports

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

Solution 11 - Angular

Easiest way

As mentioned here, please simply use Location which come from @angular/common.

Example

> In your component.ts

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


@Component({...})
export class AuthenticationComponent {
	constructor(private _location: Location) {}

	public returnPreviousUrl(): void {
		this._location.back();
	}
}

> In your component.html

<div (click)="returnPreviousUrl()">return</div>

Solution 12 - Angular

Pretty simple by using previousNavigation object:

this.router.events
  .pipe(
    filter(e => e instanceof NavigationEnd && this.router.getCurrentNavigation().previousNavigation),
    map(() => this.router.getCurrentNavigation().previousNavigation.finalUrl.toString()),
  )
  .subscribe(previousUrl => {}); 

Solution 13 - Angular

I had some struggle to access the previous url inside a guard.
Without implementing a custom solution, this one is working for me.

public constructor(private readonly router: Router) {
};

public ngOnInit() {
   this.router.getCurrentNavigation().previousNavigation.initialUrl.toString();
}

The initial url will be the previous url page.

Solution 14 - Angular

This simple solution worked for me.

import 'rxjs/add/operator/pairwise';
import { Router } from '@angular/router';

export class TempComponent {
    constructor(private router: Router) {
        this.router.events.pairwise().subscribe((event) => {
            console.log(event); // NavigationEnd will have last and current visit url
        });
    };
}

Solution 15 - Angular

    import { Router, RoutesRecognized } from '@angular/router';
    import { filter, pairwise } from 'rxjs/operators';
    
    constructor(
        private router: Router
      ) {
        
      }
    
    ngOnInit(){
    this.router.events
    .pipe(filter((evt: any) => evt instanceof RoutesRecognized), pairwise())
    .subscribe((events: RoutesRecognized[]) => {
      
       let prevUrl = events[0].urlAfterRedirects;
      console.log('previous url', prevUrl);
      console.log('current url', events[1].urlAfterRedirects);
    });
    }

Solution 16 - Angular

Reference : https://stackoverflow.com/questions/61588087/get-previous-url-in-angular

Using as part of a service is better approach

    @Injectable({
      providedIn: 'root'
    })
    export class RoutingStateService
    {
      private history = [];
    
      constructor(private router: Router)
      {
        this.loadRouting();
      }
    
      public loadRouting(): void
      {
        this.router.events
          .pipe(filter(event => event instanceof NavigationEnd))
          .subscribe(({urlAfterRedirects}: NavigationEnd) => {
            this.history = [...this.history, urlAfterRedirects];
          });
      }
    
      public getHistory(): string[]
      {
        return this.history;
      }
    
      public getPreviousUrl(): string
      {
        return this.history[this.history.length - 2];
      }
    }

Next in your component on init

    ngOnInit(): void {
         this.routingStateService.loadRouting()
      }

Now you can get the previous url by calling getPreviousUrl() method from service

Solution 17 - Angular

Most up-to-date complete answer including refreshes.

the service

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

@Injectable()
export class RouterService{

    private prevUrl?: any = undefined;

    constructor(private router: Router){
        router.events.pipe(
            filter(e => e instanceof NavigationEnd),
            pairwise()          
        ).subscribe(x=>{            
           this.prevUrl = x[0].urlAfterRedirects;           
           localStorage.setItem("prevUrl", this.prevUrl);
        })
    }
    public getPrevUrl(){
        console.log(this.prevUrl)
        return this.prevUrl;
    }
    public getCurrUrl(){
        return  this.router.url;
    }
    public checkStorage(){
        console.log("checkign storage")
        this.prevUrl= localStorage.getItem("prevUrl")
    }
}

app.component

import { RouterService } from './shared/services/router-service';

export class AppComponent {

  constructor(private routerSvc: RouterService ) {}
  ngOnInit() {
    this.routerSvc.checkStorage()
  }
}

inlcuse service in App.module

@NgModule({
...
  providers: [
    RouterService
  ],

in component


import { RouterService  } from '../services/router-service';

export class MyComponent implements OnInit {

  constructor(private routerSvc: RouterService) { }
  
  ngOnInit(): void {    
    console.log(this.routerSvc.getPrevUrl())
  }

}

Solution 18 - Angular

You can try this sample code:

import {Router, RoutesRecognized, Event} from '@angular/router';
import {filter, pairwise} from 'rxjs/operators';
 
previousUrl = '';

constructor(
  private readonly location: Location, private readonly router: Router) {
    this.router.events
      .pipe(filter((evt: Event): evt is RoutesRecognized => evt instanceof RoutesRecognized), pairwise())
      .subscribe((events: RoutesRecognized[]) => {
        this.previousUrl = events[0].urlAfterRedirects;
    });
  }

Type declaration of 'any' loses type-safety. It's better to provide a more specific type.

TypeScript's any type is a super and subtype of all other types, and allows dereferencing all properties. As such, any is dangerous - it can mask severe programming errors, and its use undermines the value of having static types in the first place.

Solution 19 - Angular

There is an issue in the Angular GitHub that's being considered right now that would make this super easy, i.e., Router.previousUrl. Please put your  on the issue to make it cross the required 20 in order to make it into the backlog:

https://github.com/angular/angular/issues/45685

Solution 20 - Angular

You can simply use the solution with RXJX exemple inspiration

app.componennt.html

<p>Previous URL: {{ previousUrl }}</p>
<p>Current URL: {{ currentUrl }}</p>

app.component.ts

previousUrl: string = null
currentUrl: string = null

ngOnInit() {
    this.router.events.pipe(
      filter((event) => event instanceof NavigationEnd)
    ).subscribe((event: NavigationEnd) => {
      this.previousUrl = this.currentUrl;
      this.currentUrl = event.url;
      this.urlService.setPreviousUrl(this.previousUrl);
    });
  }

injector service

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, take } from 'rxjs';

@Injectable()
export class UrlService {
  private previousUrl: BehaviorSubject<string> = new BehaviorSubject<string>(null);
  public previousUrl$: Observable<string> = this.previousUrl.asObservable();

  constructor() { }
  setPreviousUrl(previousUrl: string) {
    this.previousUrl.next(previousUrl);
  }
}

wanted.component.ts, just implement previous function to navigate

public goToPrevious(): void {
    let obsValue = undefined;
    const sub = this.urlService.previousUrl$.pipe(take(1)).subscribe(value => obsValue = value);
    sub.unsubscribe();

    console.log('url', obsValue)
    this.router.navigateByUrl(obsValue)
}

You can also show the in previous value in template with pipe async

other.component.html

<p>Previous URL: {{ previousUrl | async }}</p>

other.component.ts

export class OtherComponent implements OnInit {
  previousUrl: Observable<string> = this.urlService.previousUrl$;
  constructor(private urlService: UrlService) { }

  ngOnInit() {
    this.urlService.previousUrl$.subscribe((previousUrl: string) => {
      console.log('previous url: ', previousUrl);
    });
  }
}

Solution 21 - Angular

All the Above ANSWER will be loads URL multiple times. If user visited any other component also, these code will loads.

So better to use, Service creating concept. https://community.wia.io/d/22-access-the-previous-route-in-your-angular-5-app

This will works well in all versions of Angular. (please Make sure to add it to the providers array in your app.module file! )

Solution 22 - Angular

I had similar problem when I had wanted to back to previous page. Solution was easier than I could imagine.

<button [routerLink]="['../']">
   Back
</button>

And it returns to parent url. I hope it will help someone ;)

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
Questionchandradot99View Question on Stackoverflow
Solution 1 - AngularBYUNGJU JINView Answer on Stackoverflow
Solution 2 - AngularGünter ZöchbauerView Answer on Stackoverflow
Solution 3 - AngularJulianoView Answer on Stackoverflow
Solution 4 - AngularFranklin PiousView Answer on Stackoverflow
Solution 5 - AngularMhd Louay Al-oshView Answer on Stackoverflow
Solution 6 - AngularPraveen PandeyView Answer on Stackoverflow
Solution 7 - AngularknoefelView Answer on Stackoverflow
Solution 8 - AngularVictor OliveiraView Answer on Stackoverflow
Solution 9 - AngularvladymyView Answer on Stackoverflow
Solution 10 - AngularWaleed EmadView Answer on Stackoverflow
Solution 11 - AngularHugo BayoudView Answer on Stackoverflow
Solution 12 - AngularDmitrij KubaView Answer on Stackoverflow
Solution 13 - AngularC0ZENView Answer on Stackoverflow
Solution 14 - AngularSahil RalkarView Answer on Stackoverflow
Solution 15 - AngularShashwat GuptaView Answer on Stackoverflow
Solution 16 - AngularGuru CseView Answer on Stackoverflow
Solution 17 - AngularpsykressxView Answer on Stackoverflow
Solution 18 - AngularJessica RodriguezView Answer on Stackoverflow
Solution 19 - Angularuser1902183View Answer on Stackoverflow
Solution 20 - AngularNevada StoneView Answer on Stackoverflow
Solution 21 - AngularABHILASHA K.MView Answer on Stackoverflow
Solution 22 - AngularDiPixView Answer on Stackoverflow