Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine previous page URL in Angular?

People also ask

How do I find the previous route URL?

In any component you want to access the previous url, you need to import the url service, define it in its constructor, subscribe to the previous url observable, and set it as a variable in the component. Now you can use the previous url anywhere in your component, and receive any changes to its value!

How can I get current URL in Angular?

Steps to get current route URL in Angular. Import Router,NavigationEnd from '@angular/router' and inject in the constructor. Subscribe to the NavigationEnd event of the router. Get the current route url by accessing NavigationEnd's url property.

What is NavigationEnd in Angular?

NavigationEndlinkAn event triggered when a navigation ends successfully. class NavigationEnd extends RouterEvent { constructor(id: number, url: string, urlAfterRedirects: string) type: EventType.


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

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?


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

  //...

}

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

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

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

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