Reputation: 4247
Although this question seems to have popped up before, I can't find an answer that works for me, as the router seems to have changed a lot over the lifetime of angular.
In angular 5 I have a component where I wish to edit a user. I navigate to that component with the following code:
this.router.navigate(['editsingleuser',user.username])
Which will send me to /editsingleuser/bob
Then, from within that component I can also click on a button to edit my own user details, which uses the following code:
this.router.navigate(['editsingleuser',this.user.sub])
Which should send me to /editsingleuser/joe, but does not
Is there a parameter that I can add to the router.navigate
that forces it to load the route, as it seems to be doing some kind of caching?
I have also tried using
[routerLink]="['editsingleuser',user?.sub]"
which also has the same issue
Upvotes: 43
Views: 47730
Reputation: 1
After a lot of search and time spent, I got a simple trick. That is to create a duplicate path for the same component on route like and use them interchangeably during navigation
// on the router
route = [
{'path1',component: Component1},
{'path2',component: Component1}
];
//on the component
this.url = (this.url=='path1')?'path2':'path1';
this.router.navigate([this.url],{id: this.id});
Upvotes: 0
Reputation: 1004
I would do something like this:
constructor(private router: Router, private route: ActivatedRoute) { }
/**
* Navigate to User Details
*
* @summary Navigates to User Details Page
* @param userId: string
* @returns void
*/
navigateToUserDetails(userId: string): void {
this.router.navigate(['.', userId], { relativeTo: this.route.parent });
}
This solution avoids hardcode URL fragments in the code. Preventing issues if the 'editsingleuser' URL fragment is changed for some reason.
So, I believe the trick here is the this.route.parent if your route child path is something like :userId
Upvotes: 0
Reputation: 2574
In Angular 8, it is possible to load some other route and then return to the current active one. Just try this:
this.router.navigateByUrl('/', {skipLocationChange: true})
.then(()=>this.router.navigate(['editsingleuser',this.user.sub]));
Credits:
Upvotes: 34
Reputation: 2247
As of 5.1, Angular has a setting for route reloading. It's a parameter called
onSameUrlNavigation
https://angular.io/api/router/ExtraOptions
@NgModule({
imports: [ RouterModule.forRoot(routes, { onSameUrlNavigation: 'reload' }) ],
exports: [ RouterModule ]
})
export class AppRoutingModule {}
I suggest against using this technique though.
Angular's default behaviour does not reload the route when you navigate to the same route. It's a nice fail safe and it makes sense.
However, if you are changing the parameters, you could subscribe to the parameter change and act accordingly like this for example:
@Component({
selector: 'app-custom-edit',
templateUrl: './custom-edit.component.html',
styleUrls: ['./custom-edit.component.scss']
})
export class CustomEditComponent implements OnInit {
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.route.params.subscribe(res => {
if (+res.id === 0) this.initNew() // 'id' here is an example url parameter
else this.initExisting(+res.id)
})
}
initNew() {
//..
}
initExisting(id: number){
//..
}
}
And, by accordingly meaning, you could handle a set or reset of your component based on the parameter reality. Take it as your job, not the router's. This trigger will fire on the first initialization and when navigating to the same url with different parameters.
At the very least, it's more efficient than reloading the entire route.
Upvotes: 12
Reputation: 18944
What you want is not a strange job in Angular! I created a project in Stackblitz to show you how a component will be rendered (re-instantiated) again even if you are at the same component.
Note that you should define a route with parameter in app.routing.module for the corresponding component like below where I defined username
parameter for catalog:
RouterModule.forRoot([
{ path: 'login', component: LoginViewComponent },
{ path: 'home', component: HomeViewComponent },
{ path: 'catalog/:username', component: CatalogViewComponent },
{ path: '**', redirectTo: 'login' }
])
Then navigate to it like the following :
<a routerLink="/catalog/foo">Catalog 1</a> |
<a routerLink="/catalog/bar">Catalog 2</a>
If the URL doesn't change, there's a problem with your variables which are used as parameter. There's no difference whether you employ this.router.navigate
or [routerLink]
in this case.
And then consume it at the catalog.component.ts.
Upvotes: 1
Reputation: 737
I faced the same issue and this solved it in my case
constructor(private router: Router) {
this.router.routeReuseStrategy.shouldReuseRoute = function () {
return false;
};
}
Upvotes: 43
Reputation: 4247
The answer to this problem was that I had to subscribe to the route parameter in my EditSingleUser component, and use this value when I fetched the data for the page
In ngOnInit()
this.route.params
.switchMap((p: Params)=>{
let usr = p['username']; //read the username route parameter
return this.apiService.getUser(usr)} //call getUser with that parameter
)
.subscribe(data=> {
this.user= data
console.log("data :" + JSON.stringify(data));
this.setupFormData(); //use the resulting data to set up the form
})
Upvotes: 22
Reputation: 11696
You can't navigate to editsingleuser/joe
because you are already in editsingleuser
route. If you will to navigate from editsingleuser
to the same route, than you should change following code in your editsingleuser component:
this.router.navigate(['editsingleuser',this.user.sub]);
to this:
this.router.navigate(['/editsingleuser',this.user.sub]);
So you say to router, that you will go globaly to route editsingleuser
.
Here I create an working example for you.
Upvotes: 1