115

In the latest version of Angular 7.2.6, I'm trying to pass data in router itself

this.router.navigate(['other'], {state: {someData: 'qwert'}}

In the OtherComponent file, this.router.getCurrentNavigation() always return null

Stackblitz Link

Angular Docs - getCurrentNavigation

Angular Docs - state

2
  • 9
    Where are you calling the function? I think ngOnInit() would be too late, as the navigation has already completed github.com/angular/angular/blob/7.2.6/packages/router/src/… Commented Feb 26, 2019 at 17:38
  • In OtherComponent, and modified it to be in constructor and it worked! Commented Feb 26, 2019 at 17:42

11 Answers 11

243

You're calling the method getCurrentNavigation too late. The navigation has finished.

You need call the getCurrentNavigation method inside of the constructor:

constructor(private router: Router) {
    this.name = this.router.getCurrentNavigation().extras.state.someData;
}

Or if you want to access the navigation in ngOnInit you can do following:

ngOnInit() {
    this.name = history.state.someData;
}
Sign up to request clarification or add additional context in comments.

7 Comments

@Carlos.V no it does not! :\
this did not work for me when navigation is from InitializeApp in app.component
In my case, I was using this in ngOnInit but after awaiting for another method to complete, so it evaluated to null. Works as expected when fired independently within the ngOnInit method!
any disadvantages by using history over router.GetCurrentNavigation() ?
For issues with Angular 15+ see @Matthieu Riegler answer
|
33

Since Angular 16, there is lastSuccessfulNavigation to replace the breaking change that was introduced in v15 where getCurrentNavigation might return null.


Pre v16 answer:

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 
  }

6 Comments

This worked for me in Angular 14!
Can you please show how to access the someData property,when using the location.getState() object?
It should be location.getState().someData.
Got error: "Object is of type 'unknown'" in that case and had to define interface State { someData: any; } to receive the value of someData via const state = location.getState() as State; console.log(state.someData);. Is there a more general way to resolve the parameters from getState(), because I don't want to define interfaces all over the app, where I use certain parameters for navigation?
You can always assert as any.
|
14

change the code like this because after constructor() only the ngOnInit() gets called so the value is getting null

constructor(private router: Router) {
   this.name = this.router.getCurrentNavigation().extras.state.example;
}

Comments

7

Since Angular 16, there is lastSuccessfulNavigation to replace the breaking change that was introduced in v15 where getCurrentNavigation might return null.

5 Comments

I suggest updating your previous answer about location.getState() instead of adding another one, since it's now likely the more appropriate approach.
Property 'lastSuccessfulNavigation' is private and only accessible within class 'Router'
I just copied/pasted the error message I got when I implemented this solution... What worked for me was using getState() instead of lastSuccessfulNavigation. I am using Angular 14.
I'm using Angular 20 and its work very well with ngOnInit.
2

If your path is registered with a parameter:

{path: 'somePath/:id', component: SomeComponent}

It's important to navigate to it correctly:

this.router.navigate(['/some', id], {state: {data: id}});

Incorrect would be:

this.router.navigate(['/some'+'/'+id], {state: {data: id}});

Angular does not warn you about incorrect usage and this.router.getCurrentNavigation().extras.state is not set.

Comments

1

This happened to me because there was a promise (asynchronous process) in the Event of the NavigationEnd, before consuming the getCurrentNavigation().extras().state of the current state.

I moved the promise after and voila! It managed to get the data without first being cleaned.

Comments

0

For spec (tests), the getCurrentNavigation() on constructor don´t work, you have to use the history at ngOnInit() and mock values at history, for example:

beforeEach(() => {
    window.history.pushState({name: 'MyName', id: 1}, '', '');
}

Now your component can use this values on ngOnInit() and use on spec.:

ngOnInit(): void {
    console.log(history.state.name);
}

Comments

0

To persist state use navigateByUrl

this.route.navigateByUrl('/your-route', { state: { id:some_id, name:'your_data' } );
<a [routerLink]="['dynamic']" [state]="{ { id:some_id, name:'your_data' }}">Dynamic Data</a>

Comments

0

I find the solution as follows for angular v16:

First, set the router

const routes: Routes = [
  {
    path: 'hero/:id',
    component: ChildComponent,
  },
];

When we need to obtain the ID in our component, such as when fetching a hero using its ID, we would do the following in the component:

export class ChildComponent {
  constructor(route: ActivatedRoute) {
    route.params.subscribe((params) => // do whatever you want with params.id);
  } 
}

Now we can use @Input for that. It's as simple as that.

export class ChildComponent {
  @Input() id: string;
}

Comments

0

Angular 17.3.0

I tried several solutions mentioned in this post, but they didn't work so far with Angular 17.3.0.

What did work, however, was to use navigateByUrl() instead of navigate().

Below is an example ...

Example

Code

Component A

Component class

export class CompAComponent {

  constructor(private router: Router) {}

  navigateToB1() {
    this.router.navigate(['/route-b', { state: { msg: 'item-1' }}])
  }

  navigateToB2() {
    this.router.navigateByUrl('/route-b', { state: { msg: 'item-2' }})
  }
}

Component template

<button (click)="navigateToB1()">Go to B (navigate)</button>
<button (click)="navigateToB2()">Go to B (navigateByUrl)</button>

Component B

Component class

export class CompBComponent implements OnInit {

  constructor(private router: Router) {
    console.log(this.router.getCurrentNavigation()?.extras)
    console.log(this.router.lastSuccessfulNavigation?.extras);
  }

  ngOnInit(): void {
    console.log(this.router.lastSuccessfulNavigation?.extras);
    console.log(this.router.getCurrentNavigation()?.extras)
  }
}

App component

  <nav>
    <a class="nav-link" routerLink="route-a" routerLinkActive="active">Comp A</a> 
    |
    <a class="nav-link" routerLink="route-b">Comp B</a>
  </nav>
  <router-outlet></router-outlet>

Running the example

Using navigate()

When clicking the button that triggers navigateToB1(), the function navigates me to CompBComponent with the following output:

// ...
constructor(private router: Router) {
  console.log(this.router.getCurrentNavigation()?.extras)     // { "skipLocationChange": false }
  console.log(this.router.lastSuccessfulNavigation?.extras);  // { "skipLocationChange": false, replaceUrl": false }
}

ngOnInit(): void {
  console.log(this.router.lastSuccessfulNavigation?.extras);  // { "skipLocationChange": false, "replaceUrl": false }
  console.log(this.router.getCurrentNavigation()?.extras)     // undefined
}
// ...

Using navigateByUrl()

When clicking the button that triggers navigateToBB(), the function navigates me to CompBComponent with the following output:

// ...
constructor(private router: Router) {
  console.log(this.router.getCurrentNavigation()?.extras)     // { "state": { "msg": "item-2" } }
  console.log(this.router.lastSuccessfulNavigation?.extras);  // { "skipLocationChange": false, "replaceUrl": false }
}

ngOnInit(): void {
  console.log(this.router.lastSuccessfulNavigation?.extras);  // { "state": { "msg": "item-2" } }
  console.log(this.router.getCurrentNavigation()?.extras)     // undefined
}
// ...

Conclusion

Using navigate() didn't pass the state in all of the examples, but for some reason navigateByUrl() did.

Am I missing something here? Afaik, navigate() is just a wrapper around navigateByUrl(). Maybe it has something to do with how navigateByUrl() changes the location bar:

How to use router.navigateByUrl and router.navigate in Angular

Comments

-9

work for me Ionic 4

  • this.router.url => /app/menu/etc // current position

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.