How to reload a page in Angular 8 the proper way
Asked Answered
S

10

16

NB. I've got a set of resulting from googling but, as I explain at the end, I sense that they aren't reliable, due to diversity.

I have two utility methods - one for navigating to the parent node and one for reloading self. The first one works as supposed to, while the other one fails to cause the reload.

navigateToParent(route: ActivatedRoute) {
  const options: NavigationExtras = { relativeTo: route };
  this.router.navigate([".."], options);
}

navigateToSelf(route: ActivatedRoute) {
  this.router.routeReuseStrategy.shouldReuseRoute = () => false;
  this.router.onSameUrlNavigation = "reload";
  const self = ".";
  this.router.navigate([self]);

  // const options: NavigationExtras = { relativeTo: route };
  // this.router.navigate(["."], options);
}

I followed the answer here, with the only exception that I'd like my path navigated to, to be generic, not hard-coded. I've tried passing different parameters, like self="." and self="" etc. Nothing seems to give me the desired reload.

What do I miss?

I also tried to pick the parts from the route passed into the service's method but I only see a bunch of observables, not the actual segments. And, of course, this.router.navigate(route) only caused an error.

Googling produced a lot of hints with vastly varying suggestions (e.g. this), which leads me to the suspicion that it might be heavily dependent on the version (I'm on 8.0) and, also, that many of the suggestions, although accepted, might be misleading and more harmful in the long run, without me realizing it.

Storeroom answered 1/1, 2020 at 12:9 Comment(2)
Try this: this.router.navigate([this.router.url])Huffman
You can check my update answer working for every component reload..Hugh
H
13

You can find total working example here in this StackBlitz Link

Update First of all doing window.location.reload() is totally against of Single-Page-Application nature. rather, You can reload particular component when actually clicking on that link.. so, to do this task we have angular router. For particular component reload you can push this line of code in main app.component.ts once for full application.

mySubscription;

 constructor(private router: Router, private activatedRoute: ActivatedRoute){
    this.router.routeReuseStrategy.shouldReuseRoute = () => false;
    this.mySubscription = this.router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
         // Trick the Router into believing it's last link wasn't previously loaded
         this.router.navigated = false;
      }
    }); 
 }

above code we are going to subscribing to router-events. and then we are checking each and every router-NavigationEnd event, then just telling router, forget to add current navigation of router to its own history. So, each time whenever we are trying to reload same component each and every events are firing for that particular component only, thats a SPA.

IN app.component.ts of ngOnDestroy() we have to unsubscribe from router events, when component is destroyed.

ngOnDestroy(){
  if (this.mySubscription) {
    this.mySubscription.unsubscribe();
  }
}

Now, for example you have Home and Details component or anything else of component... You can reload each component by calling this.router.navigate([this.router.url]) this will reload all current component. for example, In home component we have reload-button and click event of that we are just calling this.router.navigate([this.router.url]). same for details component too.. or any other component..

Home.component.ts

reLoad(){
  this.router.navigate([this.router.url])
}

Details.component.ts

reLoad(){
  this.router.navigate([this.router.url])
}

You can check in updated above StackBlitz link, all working example of reloading with full router-state reloading. In browser console see each and every events of component is firing by clicking button reload().

Hugh answered 1/1, 2020 at 12:55 Comment(4)
I don't fully grasp the idea. I don't even have a /home path in my project. And I'd like to understand what I did wrong in my original approach and how to resolve that. As far I understand your example, you navigate to a hard-coded URL, aren't you? Please elaborate.Storeroom
Here main approach is skipLocationChange to reload already activated route. As I think it's your main problem to do. I showed you one demo, you can use this approach in your use-case. If possible make your stackblitz and share link to help you more.Hugh
Why do we need ngOnDestroy() here since this is the Root component and it will never destroy?Lw
After adding this.router.navigated = false the menu items do not highlighted properly for me. So I switched to Gustavo's solution.Septuor
K
25

Ok!! This example works for me without reloading the page:

In router component you have to add 'onSameUrlNavigation' to your route.

router.component:

@NgModule({
  imports: [RouterModule.forRoot(routes, { onSameUrlNavigation: 'reload' })],
  exports: [RouterModule],
})

now component you want reload

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

someFunction(){
  this.router.navigateByUrl('/route');
}
Kamala answered 20/8, 2020 at 15:51 Comment(3)
This is the best solution when using RouterModule.forChild(routes) which does not support the onSameUrlNavigation option.Tauromachy
this is a good solution but seems to be marking a whole bunch of other links as active ever since I've had it enabledCompanionate
Awesome, thank you! This solution works for Angular 13International
H
13

You can find total working example here in this StackBlitz Link

Update First of all doing window.location.reload() is totally against of Single-Page-Application nature. rather, You can reload particular component when actually clicking on that link.. so, to do this task we have angular router. For particular component reload you can push this line of code in main app.component.ts once for full application.

mySubscription;

 constructor(private router: Router, private activatedRoute: ActivatedRoute){
    this.router.routeReuseStrategy.shouldReuseRoute = () => false;
    this.mySubscription = this.router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
         // Trick the Router into believing it's last link wasn't previously loaded
         this.router.navigated = false;
      }
    }); 
 }

above code we are going to subscribing to router-events. and then we are checking each and every router-NavigationEnd event, then just telling router, forget to add current navigation of router to its own history. So, each time whenever we are trying to reload same component each and every events are firing for that particular component only, thats a SPA.

IN app.component.ts of ngOnDestroy() we have to unsubscribe from router events, when component is destroyed.

ngOnDestroy(){
  if (this.mySubscription) {
    this.mySubscription.unsubscribe();
  }
}

Now, for example you have Home and Details component or anything else of component... You can reload each component by calling this.router.navigate([this.router.url]) this will reload all current component. for example, In home component we have reload-button and click event of that we are just calling this.router.navigate([this.router.url]). same for details component too.. or any other component..

Home.component.ts

reLoad(){
  this.router.navigate([this.router.url])
}

Details.component.ts

reLoad(){
  this.router.navigate([this.router.url])
}

You can check in updated above StackBlitz link, all working example of reloading with full router-state reloading. In browser console see each and every events of component is firing by clicking button reload().

Hugh answered 1/1, 2020 at 12:55 Comment(4)
I don't fully grasp the idea. I don't even have a /home path in my project. And I'd like to understand what I did wrong in my original approach and how to resolve that. As far I understand your example, you navigate to a hard-coded URL, aren't you? Please elaborate.Storeroom
Here main approach is skipLocationChange to reload already activated route. As I think it's your main problem to do. I showed you one demo, you can use this approach in your use-case. If possible make your stackblitz and share link to help you more.Hugh
Why do we need ngOnDestroy() here since this is the Root component and it will never destroy?Lw
After adding this.router.navigated = false the menu items do not highlighted properly for me. So I switched to Gustavo's solution.Septuor
B
4

on your app-routing-module.ts pls verify you have the {onSameUrlNavigation: 'reload'}

@ngModule({
 imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: 'reload'})],
 exports: [RouterModule],
 })
Beeman answered 2/1, 2020 at 8:23 Comment(0)
Y
2

I got quite nice working solution:

Created ReloadComponent that gets current url via navigation state and does only navigation to that url which means we go for a trip: CurrentComponent -> ReloadComponent -> CurrentComponent

import { Component } from '@angular/core';
import { Navigation, Router } from '@angular/router';

@Component({
  selector: 'app-reload',
  templateUrl: './reload.component.html',
})
export class ReloadComponent {
  constructor(private router: Router) {
    const nav: Navigation = this.router.getCurrentNavigation();

    if (nav.extras && nav.extras.state) {
      if (nav.extras.state.returnUrl) {
        this.router.navigateByUrl(nav.extras.state.returnUrl);
      }
    }
  }
}

And I call it from CurrentComponent as usual:

const currentUrl = this.router.url;
this.router.navigate(['/reload'], { state: { returnUrl: currentUrl } });

No changes to app-routing.ts beside adding ReloadComponent as usual with '/reload' path.

Yahiya answered 14/3 at 9:22 Comment(1)
This is cheating! But it's a nice cheating. +1 and thanks!Storeroom
T
1

Try the following:

imports: [RouterModule.forRoot(routes, { onSameUrlNavigation: 'reload' })]
Thimbu answered 12/6, 2020 at 5:19 Comment(0)
K
1

Anyone still coming here should know that router.routeReuseStrategy is deprecated in Angular 16 and replaced by an abstract class - which can only be defined at the root of the application (I have tested this). I only want to reload from a single component so this is way too over-engineered for me.

This solution is simple, robust and worked for me without any visual glitching:

const currentUrl = this.router.url;
await this.router.navigate(['garbish']); // navigate somewhere else (anywhere will do)
await this.router.navigate([currentUrl]);

Downside: you will add to the browser history. You could probably make a holding component that is sent the currentUrl and autoforwards if you are bothered about that.

Koweit answered 11/3 at 8:28 Comment(1)
There should be a default, recommended way to reloading a component other than navi-navigating like in your sample. It's still +1 so I'm not criticizing, just stumbled that there seems not to be. Usually, that suggests that the reloading itself isn't encouraged for some other technical reason. I fear that I'm "doing it wrong"...Storeroom
F
0
public routerreuse: any;

ngOnInit(): void {
    this.routerreuse = this._router.routeReuseStrategy.shouldReuseRoute;
    this._router.routeReuseStrategy.shouldReuseRoute = (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot) => {
      return (curr != this.route.snapshot)
    };
}
   
ngOnDestroy(): void {
    this._router.routeReuseStrategy.shouldReuseRoute = this.routerreuse;
}

this should work when the same route url is changing with browser back in history. It reloads only the same content with the same route

Frequently answered 13/10, 2022 at 12:26 Comment(0)
S
-3

Try the following.

this.ngOnInit();

It works for me with same route reload.

Statvolt answered 2/1, 2020 at 7:7 Comment(2)
This is not reLoad() of page() or component. By calling ngOnInit() by yourself, it will not called all life-cycle methods, rather you are only calling just one ngOnInt(). so this is not good practice to call ngOnInit() by yourself for complete reLoad of page.Hugh
The code isn't executed in the component itself. It's done in the service. And the extra thing is that I don't know which component that's supposed to be reloaded at that certain moment. At the moment, the user needs to hit F5 to reload the window (upon which, the correct state and data is loaded as supposed to). I only want to emulate the reloading. At least at the moment.Storeroom
O
-3
<button type="button" mat-raised-button color="warn" onclick="window.location.reload();">

Window.location.reload() on Button onClick property

Olives answered 15/12, 2021 at 21:0 Comment(0)
S
-4

To Reload the same page...Try This

window.location.reload();
Strap answered 2/1, 2020 at 8:25 Comment(3)
Oh, it's so non-angular'ish, hehe. I'll give it a try, though. If it works, it works. Still, it seems that got thirteen suggestion on a dozen tries on how to do something so basic and fundamental.Storeroom
it is not the best way.Wayside
yea i have no idea why there isnt jus a router.refresh... just another missing basic functionality from google, no surpriseToshiatoshiko

© 2022 - 2024 — McMap. All rights reserved.