14

I am developing an angular2 app and I use router. I am in a page /myapp/signup. after signup I navigate the use to /myapp/login. /myapp/login can also be navigated from my home page which is /myapp. So now, when the user users /myapp/login I go back. This can be done by using location.back(). But I dont want to go back when the user is coming from /myapp/signup. So I should check if the user is coming from /myapp/signup and if so, I want to direct it to somewhere else. How can I know the previous url so that I direct the user to a specific state based on that ?

user3205675
  • 223
  • 1
  • 3
  • 8

8 Answers8

25

The pairwise operator allows to get the current together with the previous value

update  

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

export class AppComponent {
    constructor(private router: Router) {
        this.router.events
        .filter(e => e instanceof NavigationEnd)
        .pairwise().subscribe((e) => {
            console.log(e);
        });
    }
}

See also How to detect a route change in Angular?

original (super old)

Inject Router and subscribe to events and store them for later reference

constructor(private _router: Router) {
  this._router.subscribe(route => {
    this.nextRoute ...
    this.prevRoute ...
  });
Melroy van den Berg
  • 2,697
  • 28
  • 31
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Thanks for the hint! Updated. See also http://stackoverflow.com/questions/33520043/how-to-detect-route-change-in-angular-2/38080657#38080657 – Günter Zöchbauer Oct 20 '16 at 06:24
  • 1
    This approach is helping me to re-write a non-standard breadcrumb. Very handy! – Jeff Mar 01 '17 at 16:57
  • 1
    I had to go to previous page after certain operation. This solved the problem with minimal code. Thanks! – Aamir Rizwan Sep 14 '17 at 07:59
  • This doesn't work if you need the previousUrl on a route component that just loaded, this needs two navigation events while in the same component. Does the Router/ActivatedRoute not store the previous url anywhere? – Kesarion Nov 09 '17 at 10:19
  • When I tried it last time it worked for me. Can you reproduce in http://stackblitz.com? – Günter Zöchbauer Nov 09 '17 at 10:22
  • in angular 5 -> "property 'filter' does not exist on type 'Observable' " – tatsu Feb 16 '18 at 13:21
  • That's not related to Angular, only to RXJS. https://gist.github.com/btroncone/d6cf141d6f2c00dc6b35#filter Check that you have the required imports – Günter Zöchbauer Feb 16 '18 at 13:24
  • This looks like a big out of memory leak problem at some moment. Since if I log `e` I get an increasing/appending list of current and previous links.. No way this is a stable approach. – Melroy van den Berg Apr 26 '18 at 21:51
  • @danger89 can't reproduce https://stackblitz.com/edit/angular-router-basic-example-cr5ulv – Günter Zöchbauer Apr 27 '18 at 06:11
  • @GünterZöchbauer You are right. You couldn't add this to some sub-module, but only to AppComponent. That was my flaw. However, how to use the last url within another module/component? – Melroy van den Berg Apr 28 '18 at 23:16
  • 1
    Ps. I'm now using a service for this, which I think is a good practice. Moreover, what is the type of `e` when I use the **update** example above? Currently hacking it like so: ```const prev = e[0] const cur = e[1] console.log('Previous url' + prev.url) console.log('Previous url' + cur.url)``` – Melroy van den Berg Apr 29 '18 at 00:04
  • 2 navigation events are needed for pairwise to work. For example, if I open page1 and go to page2, when I examine the value on page2 there is nothing, this is because only one event has been emitted, if I go from page2 to page3 and examine the value on page3 this is when pairwise outputs the value. how could i solve this? – JulianProg Oct 13 '20 at 16:16
  • You can use startWith to make the stream emit on first navigation. – Günter Zöchbauer Oct 13 '20 at 18:42
1

Yes, I would do it this way:

@Injectable() // do not forget to register this class as a provider
export class PreviousRouteRecorder implements CanDeactivate<any> {
  constructor(private router: Router) {
  }
  canDeactivate(component: any): Observable<boolean> | boolean {
    localStorage.setItem('previousRoute', this.router.url);
    return true;
  }
}

export const ROUTES: Routes = [
  {
    path: 'first',
    component: FirstComponent,
    canDeactivate: [PreviousRouteRecorder]},
  {
    path: 'second',
    component: SecondComponent
  }
];

export class SecondComponent implements OnInit {
  ngOnInit(){
    console.log(localStorage.getItem('previousRoute'));
  }
}
Stephen Paul
  • 37,253
  • 15
  • 92
  • 74
1

Angular 6 updated code for getting previous url as string.

import { Component, OnInit } from '@angular/core';
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
            });
    }
Franklin Pious
  • 3,670
  • 3
  • 26
  • 30
0

You can do this with document.referrer

if(document.referrer !== '/myapp/signup'){
    location.back()
}
Bob van Luijt
  • 7,153
  • 12
  • 58
  • 101
  • 1
    Not working when I test it. document.referer returns nothing in all the cases. Maybe it doesnt behave the this way when in angular2 ? – user3205675 Feb 08 '16 at 21:15
  • Im using angular2 router.navigate to navigate to the new state! – user3205675 Feb 08 '16 at 21:17
  • Aha, so you are not coming from another url? The url isn't changing? – Bob van Luijt Feb 08 '16 at 21:19
  • I am coming from another URL. I am in localhost/myapp/signup and I navigate to /myapp/login USING angular Router.navigate method. For some reason document referer is always empty regardless of where I am coming from to /myapp/login. I m thinking angular should has this functionality to know which url I am coming from. – user3205675 Feb 08 '16 at 21:22
0

You can maybe leverage the OnActivate phase with the routerOnActivate method that gives you access to the previous url and the current one.

routerOnActivate(next: ComponentInstruction, prev: ComponentInstruction) {
  console.log(`Finished navigating from "${prev ? prev.urlPath : 'null'}" to "${next.urlPath}"`);
}
cexbrayat
  • 17,772
  • 4
  • 27
  • 22
0

The implementation with the pairwise will not work if the user doesn't trigger navigation event at least two times and may cause a small bug.

page 1 -> page 2 ---> navigation event triggered, but event Observable has only 1 value and thus pairwise does not emit ---> User cannot go back to page 1

page 2 -> page 3 --> event Observable now has 2 elements and pairwise emits

I wonder if there is a workaround?

Hou
  • 69
  • 1
  • 1
  • 5
  • Read the help, don't post questions and comments as answers. If you want to comment other answer and you can't do it, try to level up first. – PhoneixS Mar 16 '18 at 10:25
  • 1
    @PhoneixS Maybe you should read the help to understand that not everyone can post a comment. Such annoyance receiving notifications from you for nothing – Hou Apr 21 '18 at 18:49
  • I was only reporting the rules of this site. I have also started from 1 reputation without comments so I know how it is and this does not exempt from complying with the rules. – PhoneixS Apr 24 '18 at 09:22
  • I am having the same problem, the pairwise operator does not work as expected as commented by @Hou. Is there a solution to this? – JulianProg Oct 13 '20 at 16:12
0

You can set the previous url using a auth guard and set the previous url in any were of the application.

canActivate(route: ActivatedRouteSnapshot, snapshot: RouterStateSnapshot) {
                this.commonService.prevRouter = this.router.url;
}
Derlin
  • 9,572
  • 2
  • 32
  • 53
-1
import {Location} from '@angular/common';

 private currentLocation;
 constructor(private location: Location){
    this.currentLocation = this.location.path();  
   }

ngAfterViewInit() {
 let instance = this;
 this.router.parent.subscribe(() => {            
        if (instance.currentLocation != instance.location.path()) {
             console.log("previous -> "+instance.currentLocation+" != next -> "+instance.location.path());             
        }else{
            console.log("previous -> "+instance.currentLocation+" == next -> "+instance.location.path());
        }
    });
}
Jean Palmeira
  • 19
  • 1
  • 5