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
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
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;
}
ngOnInit but after awaiting for another method to complete, so it evaluated to null. Works as expected when fired independently within the ngOnInit method!Since Angular 16, there is lastSuccessfulNavigation to replace the breaking change that was introduced in v15 where getCurrentNavigation might return null.
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
}
someData property,when using the location.getState() object?location.getState().someData.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?any.Since Angular 16, there is lastSuccessfulNavigation to replace the breaking change that was introduced in v15 where getCurrentNavigation might return null.
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.
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);
}
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;
}
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 ...
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' }})
}
}
<button (click)="navigateToB1()">Go to B (navigate)</button>
<button (click)="navigateToB2()">Go to B (navigateByUrl)</button>
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)
}
}
<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>
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
}
// ...
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
}
// ...
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
ngOnInit()would be too late, as the navigation has already completed github.com/angular/angular/blob/7.2.6/packages/router/src/…OtherComponent, and modified it to be inconstructorand it worked!