368

Is there anyway to send data as parameter with router.navigate? I mean, something like this example, as you can see the route has a data parameter, but doing this it's not working:

this.router.navigate(["heroes"], {some-data: "othrData"})

because some-data is not a valid parameter. How can I do that? I don't want to send the parameter with queryParams.

Jota.Toledo
  • 27,293
  • 11
  • 59
  • 73
Motomine
  • 4,205
  • 5
  • 20
  • 23
  • I think it should be other way like in AngularJS, where we were able to do something like $state.go('heroes', {some-data: "otherData"}) – Motomine Jul 01 '17 at 18:55
  • Use my approach https://www.npmjs.com/package/ngx-navigation-with-data last comment by me, best for everyone – Virendra Yadav Nov 28 '18 at 06:23
  • https://stackoverflow.com/a/69420764/7186739 – Billu Oct 05 '21 at 08:00
  • 2
    Routing is a complex feature in Angular and definitely worth learning! Here you may find interesting details about passing data via the routing: https://indepth.dev/tutorials/angular/indepth-guide-to-passing-data-via-routing This guide goes through various techniques about using static data in routing definition and dynamic data (state) during specific navigation. – Maciej Wojcik Jul 23 '22 at 11:47

10 Answers10

874

There is a lot of confusion on this topic because there are so many different ways to do it.

Here are the appropriate types used in the following screen shots:

private route: ActivatedRoute
private router: Router

1) Required Routing Parameters:

enter image description here

2) Route Optional Parameters:

enter image description here

3) Route Query Parameters:

enter image description here

4) You can use a service to pass data from one component to another without using route parameters at all.

For an example see: https://blogs.msmvps.com/deborahk/build-a-simple-angular-service-to-share-data/

I have a plunker of this here: https://plnkr.co/edit/KT4JLmpcwGBM2xdZQeI9?p=preview

Nasta
  • 819
  • 8
  • 21
DeborahK
  • 57,520
  • 12
  • 104
  • 129
  • 4
    thank you for your answer! What is the difference between the 2) and the 3)? Because both end up adding "?parameter=" in the URL. Could you give me an example for the 4)? I can't figure out how to do it. – Motomine Jul 01 '17 at 22:38
  • I updated by answer to show the different URLs and to provide a link to a blog post and plunker on how to pass data with a service. The URL is different with optional and query parameters as shown above. Plus query parameters can be retained across routes. – DeborahK Jul 01 '17 at 22:50
  • 10
    I also have a Pluralsight course on routing that covers all of this: https://app.pluralsight.com/library/courses/angular-routing/table-of-contents You can sign up for a free week if you are interested in more information. – DeborahK Jul 01 '17 at 22:51
  • Thank you! I think I will do it with the service just because I don't want to show the parameters, but in some cases the other uses might work – Motomine Jul 02 '17 at 20:45
  • @DeborahK, I think there is a small mistake in the photo that show how to pass query parameters. It should be `this.router.navigate(['/products'], {queryParams: {filterBy: 'x', showImage: true}});` – Egel Sep 22 '17 at 14:17
  • You are correct @Egel. I'll update the screen shots. – DeborahK Dec 08 '17 at 08:25
  • passing data through shared service doesn't work if the page is refreshed. the data gets undefined – Vivek Feb 14 '18 at 06:13
  • It does if you register the service in a module, NOT in a component. I have an example that demonstrates it here: https://github.com/DeborahK/MovieHunter – DeborahK Feb 14 '18 at 16:34
  • Also worth noting that option 2 tries to serialize everything to the url, so some complex objects are lost (I had an object array get turned into `[object Object],[object Object],[object Object]`). It seems a service is your only choice in this case. – matmo Feb 22 '18 at 01:08
  • This seems really stupid on Angular's part. Sometimes developers want to display a message to their user when they change paths. Putting the message in the URL could lead to all sorts of hacks and social engineering opportunities – CodyBugstein Apr 24 '18 at 03:16
  • That's why they provided Option #4. :-) You can always build a service to retain any values you need. Any component can inject and access those values throughout the application. And then it is not on the URL. – DeborahK Apr 24 '18 at 06:33
  • is there any way to hide parameters – MeVimalkumar Apr 24 '18 at 07:32
  • @DeborahK Could you explain shortly why a Shared Service wouldn't be re instantiated upon page a refresh ? I thought the only way around this was using local storage ? I ran your code, but the data is not really 'shared' as the component refetches data upon refresh, via an http call - If I am not mistaken. – Standaa - Remember Monica May 01 '18 at 22:34
  • 3
    The data is only "shared" within the executing application. If the user refreshes the page, the entire application is reloaded from the server, so no prior state is retained in the application. Thinking about it in terms of a normal application, when a user refreshes it is like closing and reopening the application. If you need to retain state after a refresh, then you will need to store it somewhere such as local storage or on the server. – DeborahK May 02 '18 at 16:42
  • 4
    Just a small hint: `route` type is `ActivatedRoute`, not `Router`. – Arsen Khachaturyan May 18 '18 at 10:01
  • Are you referring to me? I'm curious as to why you would think that? – DeborahK Sep 02 '19 at 22:26
  • Thank you! I wish the official docs had clear examples like this. – rangfu Oct 18 '19 at 10:19
  • Don't use screenshots on SO! This is why! – lllllllllllllIllllIll Nov 14 '19 at 13:06
  • Dear @DeborahK, your Plnkr example is not working because of npm installment is failed in there. Can you please fix and let me know it works all correct? – LuDeveloper Apr 16 '20 at 05:56
  • Try this instead: https://github.com/DeborahK/Angular-Routing @LuDeveloper – DeborahK Apr 21 '20 at 06:44
  • As the accepted answer it should be nice if you'd add @Véger Lóránd his answer considering a fifth method using state. – TimNode Jun 16 '20 at 18:32
  • Is that how this is supposed to work? I should be wrapping anyone else's great answers into mine? – DeborahK Jun 16 '20 at 22:06
  • In option 4 how can I send a method? I am getting DataCloneError – umunBeing Jul 28 '21 at 08:38
  • Could you elaborate on your scenario? What are you trying to accomplish? – DeborahK Jul 28 '21 at 14:55
  • I'm getting this error on implementing method 2 - ```Cannot match any routes. URL Segment: 'movies;title=ring'```. – Mayank Kataria Aug 14 '21 at 06:05
  • This is what I was looking for. Thanks for sharing @DeborahK – Amir Nov 02 '21 at 11:18
483

There is a new method what came with Angular 7.2.0

https://angular.io/api/router/NavigationExtras#state

Send:

    this.router.navigate(['action-selection'], { state: { example: 'bar' } });

Receive:

    constructor(private router: Router) {
      console.log(this.router.getCurrentNavigation().extras.state.example); // should log out 'bar'
    }

You can find some additional info here:

https://github.com/angular/angular/pull/27198

The link above contains this example which can be useful: https://stackblitz.com/edit/angular-bupuzn

Akash Kumar Verma
  • 3,185
  • 2
  • 16
  • 32
Véger Lóránd
  • 5,192
  • 2
  • 14
  • 15
  • 36
    This is the correct answer given the new features in Angular 7. – Randy Feb 05 '19 at 02:35
  • 4
    With this approach, how would I handle a browser refresh by the user? In that case the data in the navigation extras seems to go away, so there is no chance to use it again on refresh. – tobi_b Feb 06 '19 at 09:32
  • 1
    @tobi_b I think you are right, after refresh you can not reach it. If you need it after refresh, methods in the accepted answer will be better. – Véger Lóránd Feb 12 '19 at 14:09
  • ProTip: See the stackblitz in the answer to get this to work. – P.Brian.Mackey Feb 28 '19 at 18:46
  • Reading the pull for this, it isn't clear to me that this is intended to replace the paramMap method, From the pull author: getCurrentNavigation() will return the currently executing navigation. It will return null if there is no currently executing navigation (in other words, the application is in a stable state). – IrishDubGuy Mar 28 '19 at 14:23
  • 10
    Yep that is why you only can get the data from the this.router.getCurrentNavigation() in the constructor. If you need it elsewhere like inside ngOnInit() you can access the data trough "history.state". From the documentation: "State passed to any navigation. This value will be accessible through the extras object returned from router.getCurrentNavigation() while a navigation is executing. Once a navigation completes, this value will be written to history.state when the location.go or location.replaceState method is called before activating of this route." – Véger Lóránd Apr 01 '19 at 07:16
  • 38
    Also make sure you don't try to recieve an extras object in `ngOnInit()` as `this.router.getCurrentNavigation().extras` – hastrb Apr 15 '19 at 09:41
  • What if are navigation to external url as route.navigate(['/externalUrlRedirect', {externalUrl: 'http://google.com'}], {state: {data{name:'mayank'}}}); than how to receive the same at other side . I had tried history.state but that only returns navigationId : 1 ? – Mayank Aug 09 '19 at 18:08
  • @VégerLóránd @hastrb - why can't we use this in `ngOnInit()` – Aakash Goplani Jun 04 '21 at 14:15
  • 3
    @KinleyChristian Check out this answer, if you have further questions let me know! https://stackoverflow.com/a/54891361/4222504 – Véger Lóránd Jun 07 '21 at 06:03
  • What will happen if user reloads ? Its coming undefined :'( – Piyush Sep 24 '21 at 15:46
  • 1
    Indeed, with this solution, you can not reload the page because you will lose the data. You can implement some guards to check if the data is actually there and if not (because of reloading) you just navigate back the user to that page where he can "grab" it. Here is a [video](https://www.youtube.com/watch?v=JqCG3uhZQv0) that describes very well the differences between the different solutions. Also at [15:27](https://youtu.be/JqCG3uhZQv0?t=927) the video mentions the reload problem. – Véger Lóránd Sep 27 '21 at 09:10
  • If you are using this method to pass data between components than data will not be available once you refresh the page. Since you need to read the data from browser’s history object: like history.state.data and history will be cleared on page refresh. @VégerLóránd – Amir Nov 02 '21 at 11:14
  • @Amir Yes this is what I have said in my previous comment – Véger Lóránd Nov 03 '21 at 10:12
69

Latest version of angular (7.2 +) now has the option to pass additional information using NavigationExtras.

Home component

import {
  Router,
  NavigationExtras
} from '@angular/router';
const navigationExtras: NavigationExtras = {
  state: {
    transd: 'TRANS001',
    workQueue: false,
    services: 10,
    code: '003'
  }
};
this.router.navigate(['newComponent'], navigationExtras);

newComponent

test: string;
constructor(private router: Router) {
  const navigation = this.router.getCurrentNavigation();
  const state = navigation.extras.state as {
    transId: string,
    workQueue: boolean,
    services: number,
    code: string
  };
  this.test = "Transaction Key:" + state.transId + "<br /> Configured:" + state.workQueue + "<br /> Services:" + state.services + "<br /> Code: " + state.code;
}

Output

enter image description here

Hope this would help!

dev-nish
  • 771
  • 6
  • 4
  • 6
    I keep getting "navigation is null". I have tried several examples... – AppDreamer Nov 19 '20 at 03:03
  • 13
    This is old, but for future visitors – you _have_ to call it inside the constructor. https://stackoverflow.com/a/54891361/2950032 – maazadeeb Apr 28 '21 at 00:48
  • Can you still access the state data after a page refresh? – Sofía Jul 02 '21 at 15:31
  • ok I just tested this myself, and it works perfectly only directly after routing to the new component from the old one. Once you reload the page, the state is undefined : ( – Sofía Jul 02 '21 at 15:49
  • This works perfectly till the user reload the page. Then state will be undefined. :( – Piyush Sep 24 '21 at 15:42
4

I needed access to the data in CustomRouteReuseStrategy and I couldn't inject the Router there due to a circular dependency but you can use the Location object to read the state as well.

Send:

    this.router.navigate(['action-selection'], { state: { example: 'bar' } });

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

    constructor(private location: Location) {
      console.log(this.location.getState().example); // should log out 'bar'
    }
AliF50
  • 16,947
  • 1
  • 21
  • 37
  • This way works well. If you want to use it entirely in the template, provide your `state` as bound input to the same element you're providing `routerLink` to. Eg: `` – Aaron J Jun 21 '23 at 18:57
3

Since Angular 15, this.router.getCurrentNavigation() might return null, because the component is instantiated after the navigation.

The alternative is to access the state from the Location (the one from @angular/common)

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

  constructor(private location: Location) {
    location.getState() // do what you want 
  }
Matthieu Riegler
  • 31,918
  • 20
  • 95
  • 134
2

In navigateExtra we can pass only some specific name as argument otherwise it showing error like below: For Ex- Here I want to pass customer key in router navigate and I pass like this-

this.Router.navigate(['componentname'],{cuskey: {customerkey:response.key}});

but it showing some error like below:

Argument of type '{ cuskey: { customerkey: any; }; }' is not assignable to parameter of type 'NavigationExtras'.
  Object literal may only specify known properties, and 'cuskey' does not exist in type 'NavigationExt## Heading ##ras'

.

Solution: we have to write like this:

this.Router.navigate(['componentname'],{state: {customerkey:response.key}});
Yucel Bayram
  • 1,653
  • 2
  • 22
  • 41
1

@dev-nish Your code works with little tweaks in them. make the

const navigationExtras: NavigationExtras = {
  state: {
    transd: 'TRANS001',
    workQueue: false,
    services: 10,
    code: '003'
  }
};

into

let navigationExtras: NavigationExtras = {
  state: {
    transd: '',
    workQueue: ,
    services: ,
    code: ''
  }
};

then if you want to specifically sent a type of data, for example, JSON as a result of a form fill you can send the data in the same way as explained before.

0
getStateById(stateId) {
        return this.http.get<any>(environment.user_service_url + "/getStateById",
 {params:{"stateId": stateId}});
    }
MD Ashik
  • 9,117
  • 10
  • 52
  • 59
ANKIT MISHRA
  • 558
  • 4
  • 13
0

When the NavigationEnd event is emitted, it retrieves the current navigation state using this.router.getCurrentNavigation(). If there is a navigation state available in the extras property of the navigation object, it logs the state to the console.

constructor(
    private router: Router,
    private activeRoute: ActivatedRoute
  ) {

    this.router.events
      .pipe(
        filter((event) => event instanceof NavigationEnd),
        takeUntil(this.unsubscribe$)
      )
      .subscribe((event) => {
        const navigation = this.router.getCurrentNavigation();
        if (navigation && navigation.extras.state) {
          console.log(navigation.extras.state);
        }
      });
}


  ngOnDestroy(): void {
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }

Explanation from ChatGPT:

  • The this.router.events property represents an observable that emits events related to navigation in the router.

  • The pipe method allows you to chain multiple operators to the observable.

  • In this case, the filter operator is used to only allow NavigationEnd events to pass through. This ensures that the code inside the subscribe callback is only executed when a navigation ends.

  • The takeUntil operator is used to complete the observable when the this.unsubscribe$ subject emits a value. This is done to clean up the subscription when the component is destroyed.

  • Finally, inside the subscribe callback, the current navigation state is retrieved using this.router.getCurrentNavigation(). If there is a navigation state available and it has a state property in the extras object, the state is logged to the console.

NB: In the ngOnDestroy method, the this.unsubscribe$.next() method is called to emit a value and complete the this.unsubscribe$ subject, which will in turn complete the takeUntil operator and unsubscribe from the router events.

Optimize Code:

this.router.events
  .pipe(
    filter((event) => event instanceof NavigationEnd),
    take(1) // Only take the first event
  )
  .subscribe((event) => {
    const navigation = this.router.getCurrentNavigation();
    if (navigation && navigation.extras.state) {
      console.log(navigation.extras.state);
    }
  });

MD Ashik
  • 9,117
  • 10
  • 52
  • 59
-15

Best I found on internet for this is ngx-navigation-with-data. It is very simple and good for navigation the data from one component to another component. You have to just import the component class and use it in very simple way. Suppose you have home and about component and want to send data then

HOME COMPONENT

import { Component, OnInit } from '@angular/core';
import { NgxNavigationWithDataComponent } from 'ngx-navigation-with-data';

@Component({
 selector: 'app-home',
 templateUrl: './home.component.html',
 styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

constructor(public navCtrl: NgxNavigationWithDataComponent) { }

 ngOnInit() {
 }

 navigateToABout() {
  this.navCtrl.navigate('about', {name:"virendta"});
 }

}

ABOUT COMPONENT

import { Component, OnInit } from '@angular/core';
import { NgxNavigationWithDataComponent } from 'ngx-navigation-with-data';

@Component({
 selector: 'app-about',
 templateUrl: './about.component.html',
 styleUrls: ['./about.component.css']
})
export class AboutComponent implements OnInit {

 constructor(public navCtrl: NgxNavigationWithDataComponent) {
  console.log(this.navCtrl.get('name')); // it will console Virendra
  console.log(this.navCtrl.data); // it will console whole data object here
 }

 ngOnInit() {
 }

}

For any query follow https://www.npmjs.com/package/ngx-navigation-with-data

Comment down for help.

Community
  • 1
  • 1
Virendra Yadav
  • 400
  • 3
  • 9