Search code examples
angulartypescriptangular5routerlink

Angular 5 RouterLink does not work with same path but different parameters


I have a anchor element with a RouterLink element that takes parameters. The parameters are necessary in order to navigate to the correct page. Now the router link works when I navigate the page from a different path. For instance my router module looks like this:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { MoviesComponent } from './movies/movies.component';
import { MovieReviewComponent } from './movie-review/movie-review.component';
import { LoginComponent } from './login/login.component';
import { AdminComponent } from './admin/admin.component';
const routes: Routes = [
  { path: '', component: MoviesComponent },
  { path: 'movies', component: MoviesComponent },
  { path: 'movies/:movieTitle/:year', component: MovieReviewComponent },
  { path: 'login', component: LoginComponent },
  { path: 'admin', component: AdminComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

And I have a navigation component located outside the router-outlet like this:

<app-navigation></app-navigation>
<app-messages></app-messages>
<div id="main-layout" class="row p-3">
  <section class="col-12 col-xm-12 col-md-3">hi</section>
  <section class="col-12 col-xm-12 col-md-6">
    <router-outlet></router-outlet>
  </section>
  <section class="col-12 col-xm-12 col-md-3">lo</section>
</div>

My navigation has a search bar that uses RouterLink to route to path 'movies/:movieTitle/:year' and works as long as I'm coming from a path that isn't like 'movies/:movieTitle/:year'. If the paths are similar angular will not rerender even if the movieTitle and year arguments are different.

For example if I'm at home '/' or 'movies' I can use the navbar to successfully go to 'movies/The%20Dark%20Knight/2008'. But if I'm on 'movies/The%20Dark%20Knight/2008' I cannot use the navbar to go to '/movies/Taken/2008'. I believe this has to do with Angular trying to decrease rerendering for similar paths, but how do I get Angular to change views when the same path-type has different argument?

Extra Info

  • Even when the route fails to render a new view the path url changes in the browser and it is the same url for when the page change is successfull
  • I have angular navigation events in my navigation component. I can confirm that navigation starts and that there is no navigation error. Still have to test if it cancels or not.

Answer

As the answer says I needed to subscribe to the params. Previously when I was acquiring the params I was using a snapshot:

movieTitle = this.route.snapshot.paramMap.get('movieTitle');

Now I get the params directly and subscribe to them:

this.route.params.subscribe(params => {
      this.movieService.getMovie(params['movieTitle'], params['year'])
        .subscribe(movie => {
          this.movie = movie
        })
    })

Solution

  • Routes with empty path and no children should have pathMatch: 'full'

    { path: '', component: MoviesComponent, pathMatch: 'full' },
    

    also the order of routes matters. More specific routes should come first:

    { path: 'movies/:movieTitle/:year', component: MovieReviewComponent },
    { path: 'movies', component: MoviesComponent },
    

    If only route parameters change, but the route stays the same, Angular reuses the component. You need to subscribe to params to get notified about changes. The URL is still updated.