160

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 
  }
];
Lazar Ljubenović
  • 18,976
  • 10
  • 56
  • 91
chandradot99
  • 3,616
  • 6
  • 27
  • 45

25 Answers25

165

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);
});
Vinícius Félix
  • 8,448
  • 6
  • 16
  • 32
BYUNGJU JIN
  • 1,838
  • 2
  • 11
  • 13
  • 3
    Implemented as a service and it works great. I am using angular 6.1.7. – A. El Idrissi Oct 04 '18 at 11:37
  • 7
    @tjvg1991 Refreshing page means you lost memory data. if you keep the previous data, you need to use localStorage or cookie. (save data at your local not memory) – BYUNGJU JIN May 07 '19 at 03:08
  • @BYUNGJUJIN Thanks for this! – john Sep 14 '20 at 23:23
  • @ BYUNGJU JIN thank you works for me. how do i get the value of param from the redirect link say for example events[0].urlAfterRedirects gives me '/inventoryDetails;test=0;id=45', I want to get the value of id from this. How can i do without using subString. – Geek Oct 26 '20 at 17:29
  • @JNPW your url may '/inventoryDetails?test=0&id=45'. we call that 'query parameter'. check like this out : https://stackoverflow.com/questions/47455734/how-to-get-query-parameters-from-url-in-angular-5 – BYUNGJU JIN Oct 27 '20 at 03:10
  • @BYUNGJUJIN How we can unsubscribe this event? – app Dec 09 '20 at 21:42
  • @BYUNGJUIN store the return value of `subscribe()` in a field and call `unsubscribe()` on it in `ngOnDestroy()`. There should be severs. questions with examples about unsubscribing here on SO. – Günter Zöchbauer Dec 10 '20 at 04:08
  • @BYUNGJUIN store the return value of `subscribe()` in a field and call `unsubscribe()` on it in `ngOnDestroy()`. There should be severs. questions with examples about unsubscribing here on SO. – Günter Zöchbauer Dec 10 '20 at 04:08
  • 2
    @BYUNGJUIN store the return value of `subscribe()` in a field and call `unsubscribe()` on it in `ngOnDestroy()`. There should be severs. questions with examples about unsubscribing here on SO. – Günter Zöchbauer Dec 10 '20 at 04:09
  • 1
    @app please check this out for unsubscribe : https://www.malcontentboffin.com/2017/12/Unsubscribe-from-Navigation-Events.html – BYUNGJU JIN Dec 11 '20 at 03:25
103

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 How to detect a route change in Angular?

Robert
  • 2,357
  • 4
  • 25
  • 46
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 68
    This does not list the previous route for me, only the current route. – David Aguirre Apr 05 '17 at 16:58
  • 2
    Depends on what you expect. The first time it's `null` because there is no previous route. You also need to do this on the root router, otherwise you'll only get when you navigate between child routes of this component. – Günter Zöchbauer Apr 05 '17 at 17:01
  • 12
    This doesn't give previous url when the constructor is executed for the first time. – Ekaitz Hernandez Troyas Jul 27 '17 at 20:34
  • 11
    What value do you expect as previous url when the the constructor is executed for the first time? – Günter Zöchbauer Jul 28 '17 at 03:04
  • 2
    Got error Property 'url' does not exist on type 'RouteConfigLoadStart'. – Yasar Arafath Sep 08 '17 at 06:29
  • Can't imagine if you have `.filter(event => event instanceof NavigationEnd)` as shown in my code – Günter Zöchbauer Sep 08 '17 at 06:31
  • 1
    This does not work with Angular 4, see https://github.com/angular/angular/issues/14976 – Chris Herbst Oct 14 '17 at 13:47
  • @ChrisHerbst I don't get what you mean. The linked issue was closed as invalid – Günter Zöchbauer Oct 14 '17 at 15:31
  • @GünterZöchbauer if I use the above code I get this error: Property 'url' does not exist on type 'Event' , which led me to the issue I mentioned. Am I missing something? – Chris Herbst Oct 14 '17 at 15:43
  • Can't imagine. Thw docs say it's there https://angular.io/api/router/NavigationEnd. Perhaps you can create a stackblitz.com to reproduce. – Günter Zöchbauer Oct 14 '17 at 15:45
  • 1
    @GünterZöchbauer thank you for the help, have reproduced https://angular-6seodp.stackblitz.io. The error in console TypeError: this.router.events.filter is not a function and the error in editor Property 'url' does not exist on type 'Event'. Property 'url' does not exist on type 'RouteConfigLoadStart'. – Chris Herbst Oct 14 '17 at 16:43
  • @ChrisHerbst the link doesn't seem to work. You need to use the share feature to generate a sharable link. – Günter Zöchbauer Oct 16 '17 at 07:33
  • 1
    @YasarArafath @ChrisHerbst issue is about typescript, event is collection of events, not NavigationEnds, I've done this `this.previousUrl = (e as NavigationEnd).url`, typescript 2.2.2. – Nikita Dec 04 '17 at 11:38
  • 4
    not work for me - in NavigationEnd.url have current url – Nikita Dec 04 '17 at 11:41
  • Maybe this solution not work for me because I've navigated with router.navigate(['/absolute', 'path']) – Nikita Dec 04 '17 at 11:45
  • I guess its better to save previousUrl in services then it will be updated otherwise it will be always null|undefined – vladymy Dec 15 '17 at 14:10
  • @vladymy you're right. If this is a component that gets destroyed when you navigate away, the value is lost, but if you inject the Router into a service and add the code above into a service, you have both at once. – Günter Zöchbauer Dec 15 '17 at 14:12
  • @GünterZöchbauer, I'm not sure if that solution works because that code will be executed twice and if you store the previous url to a variable then that variable will be overridden by the current url (because the code gets executed twice). Do you have any workarounds for that? – Aiguo Dec 21 '17 at 17:04
  • @Aiguo why do you think it's executed twice? Can you reproduce in http://stackblitz.com? It's a while I tried it last time but I'm sure it worked back then – Günter Zöchbauer Dec 21 '17 at 17:13
  • 1
    for those who are getting error 'url' does not exist on type 'Event' try this syntax: e['url'] Btw my previousUrl variable is returning 'undefined' i see in my console that console.log('prev:', this.previousUrl); is being printed twice, anybody has any idea why is it happening? the first console.log('prev:', this.previousUrl); prints the correct url but somehow gets overwritten and prints 'undefined' in next line. – Sushmit Sagar Jan 24 '19 at 06:25
  • Hi @GunterZochbauer.......I tried this approach in angular 9 but router.event doesn't fire at first time....could you please help me to get this in angular 9.....thanks... – Ricky Jul 27 '20 at 13:19
  • @Ricky it's a long time ago I looked into this. Perhaps the pairwise operator in the linked answer is of any use in your use case. – Günter Zöchbauer Jul 27 '20 at 15:38
  • @GünterZöchbauer How we can unsubscribe this event? – app Dec 09 '20 at 21:41
  • This provides only the current URL not the previous one. – Deepshikha Chaudhary Jun 01 '21 at 15:13
  • @DeepshikhaChaudhary why do you think that? When the 2nd event arrives the variable holds the previous value and then overrides it with the current, so that the next time it again has the previous. If you want to bind to it you beed to store it in yet another variable before it is overridden with the new value. I would now use the `pairwise()` operator for that, instead of doing it manually. – Günter Zöchbauer Jun 02 '21 at 04:30
  • @GünterZöchbauer Yes, I used the pairwise() operator to solve my issue. – Deepshikha Chaudhary Jun 03 '21 at 14:05
  • Nothing happens for me ... – PalmThreeStudio Jan 29 '22 at 16:20
  • This does not work if you change url from Address bar – Sanjay Sahani May 06 '22 at 12:15
  • @SanjaySahani it can't work if you change the url in the address bar because then the app is reloaded and everything re-initialized. You might have a look at the browser history API to get what you want, but it might not be possible for privacy reasons. You wouldn't want every page to be able to see what other pages you had visited previously. – Günter Zöchbauer May 10 '22 at 03:48
  • Does not work, only returning current URL – Rakesh Chaudhari Jun 04 '22 at 11:10
79

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

  //...

}
SwissCodeMen
  • 4,222
  • 8
  • 24
  • 34
Juliano
  • 2,422
  • 21
  • 23
  • 3
    I think this is the most elegant solution. Try to merge this code with the new filter & pairwise solution of: https://stackoverflow.com/a/35287471/518879 – Melroy van den Berg Apr 28 '18 at 23:21
  • 3
    Ps. Don't forget to add this RouterExtService to the apps-routing.module.ts (in my case), like so: `@NgModule({ ..., providers: [RouterExtService]}) export class AppRoutingModule { }` – Melroy van den Berg Apr 28 '18 at 23:50
  • OK there is a big problem with this service solution.. In my case I call the `routerExtService.getPreviousUrl()` method in the constructor of a service used in a component. For some reason this called earlier than the actual update. Meaning we have a timing dependency! I think its much easier to use Subject. – Melroy van den Berg Apr 29 '18 at 00:28
  • Well, it worked fine for me in a small project. Maybe it needs some tweak to suit your needs. Have you solved the issue? – Juliano May 11 '18 at 19:47
  • I'm currently using the so called [URL Matrix parameters](https://www.w3.org/DesignIssues/MatrixURIs.html) to 'store' my state in my URL, by default the browser URL stores the state now when using the back button. `let params = new HttpParams({fromString: retrieveURL}).set('name', 'victor') const paramsObject = params.keys().reduce((obj, key) => { obj[key] = params.get(key) return obj }, {}) this.router.navigate([paramsObject], { relativeTo: this.route })` – Melroy van den Berg May 11 '18 at 23:28
  • I agree with danger89, in fact you dont even get the correct value if you put it in ngAfterViewInit, but I have a workaround... use setTimeout to get it to trigger once the route stuff has settled, ie. ```ngAfterViewInit() { setTimeout(() => { console.log(this.routerExtService.getPreviousUrl()) }, 0); }``` – Ethan Joffe May 24 '18 at 18:32
  • For those edge cases it would be possible to expose a simple event, like an onPreviousUrlResolved(urlPath). Someone with a little more experience in Angular could point the most elegant way to achieve this. I'm not an Angular expert. – Juliano May 25 '18 at 13:44
  • maybe only missing thing is to set previousUrl on NavigationStart and not on NavigationEnd. this can be tweaked to any usecase. just use needed https://angular.io/api/router/RouterEvent – Eduard Void Aug 12 '19 at 14:38
  • In Angular 7, I declared the router as public in the service's constructor: `export class RouterExtService { /* */ constructor(public mRouter: Router) { /* */} } ` And added the `RouterExtService` in `AppModule` to the `providers` array. – Nasser Boukehil Feb 10 '20 at 16:36
  • The most elegant answer I found for the issues. – Charith Hettiarachchi Jun 11 '20 at 08:01
  • Awesome solution, was stuggling to find something like this for hours +1 – o_in25 Apr 16 '23 at 22:27
31

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
  });
}
Trevor
  • 13,085
  • 13
  • 76
  • 99
Franklin Pious
  • 3,670
  • 3
  • 26
  • 30
22

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]);
  }
con
  • 2,358
  • 25
  • 33
Louay Al-osh
  • 3,177
  • 15
  • 28
  • This works really well. But I have a quick question. Do you ever unsubscribe? – w0ns88 May 28 '20 at 13:17
  • add take(1) like this -> pairwise() , take(1)).subscribe((e: any) – Mukus Jun 29 '20 at 04:32
  • 3
    Note that if you use `@Injectable({ providedIn: 'root' })` the service is automatically loaded into the root module (AppModule) of the project and thus you don't have to manually provide it to the `app.module`. See [the docs](https://angular.io/guide/providers) for details. It's not necessary to unsubscribe from router Observables as stated in this [answer](https://stackoverflow.com/questions/41138081/do-i-have-to-unsubscribe-from-activatedroute-e-g-params-observables) – Hkidd Sep 12 '20 at 10:06
  • When I am subscribing to the previousUrl behaviorSubject, the this.previousRoutePath.next(event[0].urlAfterRedirects); is getting called after I get value in previousUrl. so it always gives currentValue (initial) and not what we got from above line – Hope Mar 15 '21 at 07:20
16

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);
              }
            });
Praveen Pandey
  • 1,675
  • 3
  • 13
  • 17
13

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';
Victor Oliveira
  • 545
  • 7
  • 13
13

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) {}
}
knoefel
  • 5,991
  • 3
  • 29
  • 43
5

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>
Hugo Bayoud
  • 149
  • 1
  • 5
4

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';
Waleed Emad
  • 109
  • 1
  • 8
3

@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);
            }
          });
      }
vladymy
  • 382
  • 2
  • 6
3

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 => {}); 
Dmitrij Kuba
  • 998
  • 9
  • 14
  • As of May 2022 the filter function in this answer has a compilation error, it should be: `filter(e => e instanceof NavigationEnd && this.router.getCurrentNavigation().previousNavigation != null)` – nevada_scout May 26 '22 at 13:35
2

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

}
liam smith
  • 21
  • 3
  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 16 '21 at 06:13
2

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.

Jessica Rodriguez
  • 2,899
  • 1
  • 12
  • 27
2

Angular 12

const prevUrl = this.router.getCurrentNavigation().previousNavigation?.finalUrl.toString();
console.log(prevUrl);
Austin
  • 115
  • 1
  • 10
0

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.

C0ZEN
  • 894
  • 11
  • 41
0

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
        });
    };
}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Sahil Ralkar
  • 2,331
  • 23
  • 25
0
    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);
    });
    }
raaaay
  • 496
  • 7
  • 14
Shashwat Gupta
  • 5,071
  • 41
  • 33
0

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

raaaay
  • 496
  • 7
  • 14
Guru Cse
  • 2,805
  • 2
  • 18
  • 15
0

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

user1902183
  • 3,203
  • 9
  • 31
  • 48
0

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);
    });
  }
}
Nevada
  • 143
  • 1
  • 10
0

You can fire an Angular service at the first start of your application like below. Be careful to import and use this service in your app root module.

Navigation Service

import {Inject, Injectable, PLATFORM_ID} from "@angular/core";
import { Subject } from "rxjs";
import { untilDestroyed } from "@ngneat/until-destroy";
import { filter, map, pairwise } from "rxjs/operators";
import { NavigationEnd, Router } from "@angular/router";

export interface ITFNavigationEnd {
    id: number;
    url: string;
    urlAfterRedirects: string;
}

export interface ITFPrevAndCurrentUrl {
    previousUrl: string;
    currentUrl: string;
}

@Injectable()
export class NavigationService {
    
    private subjectPrevAndCurrUrl: Subject<ITFPrevAndCurrentUrl> = new Subject<ITFPrevAndCurrentUrl>();
    public prevAndCurrUrl$ = this.subjectPrevAndCurrUrl.asObservable();

    private urlHistory: string[] = [];

    private _previousUrl: string;
    private _currentUrl: string;

    private firstRecord: boolean = false;

    set previousUrl(url: string) {
        this._previousUrl = url;
    }

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

    set currentUrl(url: string) {
        this._currentUrl = url;
    }

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

    constructor(@Inject(PLATFORM_ID) private platformId: any,
                private router: Router) {

        // Record changing of all url
        this.recordUrlHistory();
    }

    private recordUrlHistory(): void {

        // Quantify initial value for current value
        this.currentUrl = this.router.url;

        // Only works first time of calling this function
        if (!this.firstRecord) {
            this.firstRecord = true;
            this.urlHistory.push(this.getCurrentUrl(this.router));
        }

        this.router.events
            .pipe(
                untilDestroyed(this),
                filter(event => event instanceof NavigationEnd),
                pairwise(),
                map(event => {
                    return {
                        previousUrl: (event[0] as ITFNavigationEnd).url,
                        currentUrl:(event[1] as ITFNavigationEnd).url,
                    } as ITFPrevAndCurrentUrl;
                }),
            )
            .subscribe((response: ITFPrevAndCurrentUrl) => {

                // Update current and previous url
                this.previousUrl = response.previousUrl;
                this.currentUrl = response.currentUrl;

                // Update url history
                this.urlHistory = [...this.urlHistory, response.currentUrl];

                // Broadcast new value of current and previous url value
                this.subjectPrevAndCurrUrl.next(response);
            });
    }

    public getCurrentUrl(router: Router): string {
        return router.url;
    }

    public getUrlHistory(): string[] {
        return this.urlHistory;
    }
}

App Root Module

import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app.component";

@NgModule({
    declarations: [AppComponent],
    imports: [
        BrowserModule
    ],
    providers: [NavigationService],
    bootstrap: [AppComponent]
})
export class AppModule {
}

Now, you can use the following methods and variables from the Navigation service:

  1. currentUrl: to get current URL of the page
  2. previousUrl: to get previous URL of the page
  3. getHistory(): to get all of the URLs that have been navigated so far
  4. prevAndCurrUrl$: to observe the current and previous URLs on each navigation at the moment
Kamran Taghaddos
  • 452
  • 1
  • 10
  • 22
0

The update mentioned above was merged into and released as part of Angular 16. So the solution for this is now much easier:

https://github.com/angular/angular/pull/49235
feat(router): Expose information about the last successful Navigation

https://angular.io/api/router/Router#lastSuccessfulNavigation

lastSuccessfulNavigation: Navigation | null Read-Only

The Navigation object of the most recent navigation to succeed and null if there has not been a successful navigation yet.

  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/34808495) – Ram Chander Aug 14 '23 at 07:40
-2

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

ABHILASHA K.M
  • 146
  • 1
  • 4
  • 16
-10

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

DiPix
  • 5,755
  • 15
  • 61
  • 108