Bob5421
Bob5421

Reputation: 9173

Force routerlink to refresh component

I have created a very basic angular 5 application.

I have a left menu which is always displayed (it is part of asp.net core2.0 mvc project skelton with bootstrap).

I have created 2 links in this menu:

          <li>
            <a [routerLink]='["/component/1"]'>Component 1</a>
          </li>
          <li>
            <a [routerLink]='["/component/2"]'>Component 1</a>
          </li>

As you can see, the 2 links points to the same route (same component). We just have the id which changes. Here is the route line in app.module.ts

  { path: 'component/:id', component: MyComponent, pathMatch: 'full' },

I have added some log in my component typescript class:

constructor()
{
    console.log("constructor");
}

ngOnInit()
{
    console.log("ngOnInit");
}

If i click on the first link, everything works great. But if i click to second link, my component is not reloaded. There are no calls to constructor or ngOnInit. If i click on another link which loads another component and then return to the second link, it works.

What i want to do is how can i force angular to reload component when i click on a link which points to the same component than the one actually displayed.

Thanks

Upvotes: 20

Views: 24460

Answers (4)

AdrienW
AdrienW

Reputation: 3462

The answer by Frederick Montiel was helpful to me but uses a now deprecated syntax, so here is a version for Angular 16:

Implement a RouteReuseStrategy:


import { BaseRouteReuseStrategy } from '@angular/router';
import { Injectable } from '@angular/core';

@Injectable()
export class NoRouteReuse extends BaseRouteReuseStrategy {
  shouldReuseRoute = () => false;
}

And use it in your main.ts:

import { RouteReuseStrategy } from '@angular/router';
import { NoRouteReuse } from '@config/no-route-reuse';

...

    providers: [
       ...,
       { provide: RouteReuseStrategy, useClass: NoRouteReuse }
    ]

...

Upvotes: 2

Frederick Montiel
Frederick Montiel

Reputation: 101

Use

ngOnInit(): void {
   this.router.routeReuseStrategy.shouldReuseRoute = () => false;
}

Upvotes: 7

Ishaan Srivastav
Ishaan Srivastav

Reputation: 106

The answer by Deborah works best for your case where we only have to look for changes in the queryParams.

For anyone else, if your project really requires re-rendering a component as mine did(maybe you require to call ngOninit to reevaluate something), it can be done with

constructor(private router: Router){
     // override the route reuse strategy
     this.router.routeReuseStrategy.shouldReuseRoute = function(){
        return false;
     }

     this.router.events.subscribe((evt) => {
        if (evt instanceof NavigationEnd) {
           // trick the Router into believing it's last link wasn't previously loaded
           this.router.navigated = false;
           // if you need to scroll back to top, here is the right place
           window.scrollTo(0, 0);
        }
    });
}

The thread to the discussion where I found the solution : https://github.com/angular/angular/issues/13831

Upvotes: 2

DeborahK
DeborahK

Reputation: 60596

Normally in this case, you don't reload the component. Rather, you watch for changes in the required route parameter and proceed accordingly.

In my application, I use something like this:

constructor(private route: ActivatedRoute) { }

ngOnInit(): void {
    this.route.params.subscribe(
        params => {
            const id = +params['id'];
            this.getMovie(id);
        }
    );
}

This code catches ever change to the route parameter and causes my getMovie method to be executed every time the route parameter changes.

For a complete example, check out: https://github.com/DeborahK/MovieHunter

Upvotes: 29

Related Questions