Navigating to the same route not refreshing the component?

AngularAngular2 Routing

Angular Problem Overview


I've upgraded to use the new Angular 2 router from router-deprecated and some behavior has changed.

The page I'm having issues with is a search page. We've chosen to put all the search terms in the URL using the HashLocationStrategy. The routes look like this:

const routes: RouterConfig = [
  { path: '', component: HomeComponent },
  { path: 'search/:term/:cat/:page/:sort/:size/:more', component: HomeComponent },
  { path: 'search/:term/:cat/:page/:sort/:size', component: HomeComponent },
  { path: 'search/:term/:cat/:page/:sort', component: HomeComponent },
  { path: 'search/:term/:cat/:page', component: HomeComponent },
  { path: 'search/:term/:cat', component: HomeComponent },
  { path: 'search/:term', component: HomeComponent },
  { path: 'details/:accountNumber', component: DetailsComponent }
];

I know a query string approach might be better fit for all these options but project requirements decided by other people...

Anyway if I navigate to localhost/#/search/Hello using this.router.navigate(['/search/Hello']); then the router works fine and everything is great. While on that page if I try to this.router.navigate(['/search/World']); then the URL in the browser's address bar will update accordingly but the component doesn't change at all.

Previously I could use routerCanReuse to indicate that I did want to reuse the search component and routerOnReuse would rerun the search when the navigation happened. I don't see equivalent's to these in @angular/router. How can I reload the current route with new URL parameters?

I'm running version 2.0.0-rc.3 for Angular 2 and 3.0.0-alpha.8 of @angular/router.

Angular Solutions


Solution 1 - Angular

If only the params has changes the component itself won't be initialize again. But you can subscribe to changes in the parameters that you send.

For example on ngOnInit method you can do something like this:

ngOnInit() {
    this.sub = this.route.params.subscribe(params => {
       const term = params['term'];
       this.service.get(term).then(result => { console.log(result); });
     });
  }

Solution 2 - Angular

Probably, you don't need to run ngOnInit at all. And this is advantage of the angular router. What you can do is mentioned in the previous answer - subscribe to params or paramsMap (route.paramsMap: Observable<ParamMap> with Map interface).

There is another option - You can put your data retrieving to guard and re-run resolvers and guards on params change. Put runGuardsAndResolvers: 'paramsOrQueryParamsChange' in route configuration. Now it will be:

const routes: RouterConfig = [
{ 
     path: "search/:term/:cat/:page/:sort/:size/:more", 
     component: HomeComponent, 
     runGuardsAndResolvers: 'paramsOrQueryParamsChange' 
}, 
...];

Here you can find how to request data from api in resolvers.

Solution 3 - Angular

For later versions of Angular, using ActivatedRoute to subscribe to param changes provides a simple mechanism for refreshing data.

Quoted from answer by @Evgeny Nozdrev: https://stackoverflow.com/a/68503542/1956540

For URL params (like /persons/:id):

import { ActivatedRoute } from '@angular/router';

constructor(protected activeRoute: ActivatedRoute, ...) {
    this.activeRoute.paramMap.subscribe(paramMap => {
        const id = paramMap.get('id');    // get param from dictonary
        this.load(id);                    // load your data
    });
}

Solution 4 - Angular

I faced the same problem and resolved this by making the router not to reuse the route. This can be done by writing this code in the constructor:

constructor(
    private router: Router,
) { 
    this.router.routeReuseStrategy.shouldReuseRoute = function () {
        return false;
    };
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCorey OgburnView Question on Stackoverflow
Solution 1 - AngularDoron BrikmanView Answer on Stackoverflow
Solution 2 - AngularMariia BilykView Answer on Stackoverflow
Solution 3 - AngularBatteryAcidView Answer on Stackoverflow
Solution 4 - AngularLucian BacilaView Answer on Stackoverflow