How to reload current page?
Asked Answered
M

16

58

I have a page for editing user, it has some children components inside. Each children components can change or doing some effect to its parent component.

So instead of emitting the changes to parent and updating some fields, I did a "reload" of the current page with

private route: ActivatedRoute;

reload(){
    this.router.navigate(["/admin/user/edit/"+this.user.id]);
}

Basically, it redirects to the current page. For example, the current page is http://web.info/admin/user/edit/9 it will be redirected to this page with the hope all the data inside that page reloaded with the newest data.

but it seems the angular won't redirect/reload the same page with the router.navigate

How I should reload a current page?

Edit:

Here is the reason why I need to reload the page instead of manually updating the data on the current page. I need to do updates on Other Component, when I did the update it will add something to History Component. I need to refresh the User Component and History Component together since both components affected by the changes in Other Component.

Components

Millepore answered 18/9, 2018 at 14:55 Comment(3)
Look here: github.com/angular/angular/issues/13340 You could use simply window.location.href = '...';Kopeck
i tried using window.location.href = this.router.url .. it works but it doesn't look natural / similiar with other page. I will use this as last resortMillepore
I found a better way than reload the page. instead i will reload the data that just got updated. this way faster n betterMillepore
E
35

It will work 100%. The following lines of code are responsible for page reload in my project.

load(val) {
if (val == this.router.url) {
  this.spinnerService.show();
  this.router.routeReuseStrategy.shouldReuseRoute = function () {
    return false;
  };
 }
}

Just use the following part in your code.

this.router.routeReuseStrategy.shouldReuseRoute = function () {
    return false;
  };
Empennage answered 25/9, 2018 at 6:43 Comment(3)
am using Angular 9 and this does nothing for me. window.location.reload() works but its a clunk.Rambouillet
Complete solution needs additional step:this.router.onSameUrlNavigation = 'reload'; But if you need to reload the page only in specific scenarios, you need to save router state, change to this, make reload and restore state to default.Partlet
This worked perfectly fine for my usecase. Used the 2 liner at the end after using this.router.navigateByUrl("someUrl").Chaotic
P
77

A little bit tricky to do something so simple but had no luck trying to reload and recreate the entire parent & child components with current solution.

Angular Router now provides strategy configuration to tell the Router what to do in case you navigate to the same URL as this user suggests in this GitHub issue.

First of all you can configure what to do while setting up the Router (your router module).

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

Or, if you are like me and don't want to change the entire router module behaviour you can do it with a method/function like this:

reloadComponent() {
    this._router.routeReuseStrategy.shouldReuseRoute = () => false;
    this._router.onSameUrlNavigation = 'reload';
    this._router.navigate(['/same-route']);
}

Of course you have to first inject Router in your component's constructor:

// import { Router } from '@angular/router';
...
constructor(private _router: Router){}
...

Somehow and as pointed out by @Abhiz you have to set shouldReuseRoute, with just configuring the Router by itself the page reload doesn't work with this aproach.

I've used an arrow function for shouldReuseRoutebecause new TSLint rules won't allow non-arrow functions.

Petit answered 23/7, 2019 at 5:37 Comment(5)
Thanks, the second approach (not changing entire router behavior) works great on Angular 8.Presurmise
would it affect on another routing? or will be destroyed within these changed properties and will not affect to another routers in the project?Intact
The second method actually affects other routers if you use injection. In my scenario, one of the components uses linear stepper. By changing the strategy, that component went to infinite reload. I finally go with "this.router.navigateByUrl('/', {skipLocationChange: true}).then(() => this.router.navigate(['YourCurrentRoute', this.id]));Deannedeans
Second Approach works perfectly for Angular 7 also we can have like this to preseve queryparams also this.router.navigate(['./'], { relativeTo: this.activatedRoute, queryParamsHandling: 'preserve' });Assure
I made it work without this._router.onSameUrlNavigation = 'reload';Deathblow
E
35

It will work 100%. The following lines of code are responsible for page reload in my project.

load(val) {
if (val == this.router.url) {
  this.spinnerService.show();
  this.router.routeReuseStrategy.shouldReuseRoute = function () {
    return false;
  };
 }
}

Just use the following part in your code.

this.router.routeReuseStrategy.shouldReuseRoute = function () {
    return false;
  };
Empennage answered 25/9, 2018 at 6:43 Comment(3)
am using Angular 9 and this does nothing for me. window.location.reload() works but its a clunk.Rambouillet
Complete solution needs additional step:this.router.onSameUrlNavigation = 'reload'; But if you need to reload the page only in specific scenarios, you need to save router state, change to this, make reload and restore state to default.Partlet
This worked perfectly fine for my usecase. Used the 2 liner at the end after using this.router.navigateByUrl("someUrl").Chaotic
D
33

This is the most simple solution if you just need to refresh the entire page

   refreshPage() {
    window.location.reload();
   }
Dulciana answered 12/3, 2020 at 18:22 Comment(1)
this loads all of chunks again man.. not a angular solutionSchizophrenia
R
23

Without specifying the path you can do:

constructor(private route: ActivatedRoute, private router: Router) { }

reload() {
  this.router.routeReuseStrategy.shouldReuseRoute = () => false;
  this.router.onSameUrlNavigation = 'reload';
  this.router.navigate(['./'], { relativeTo: this.route });
}

And if you use query params you can do:

reload() {
  ...
  this.router.navigate(['./'], { relativeTo: this.route, queryParamsHandling: 'preserve' });
}
Rang answered 23/7, 2020 at 16:53 Comment(0)
A
8

I have solved by this way

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

constructor(private router: Router
          , private activeRoute: ActivatedRoute) {

}
reloadCurrentPage(){
   let currentUrl = this.router.url;
   this.router.navigateByUrl('/', {skipLocationChange: true}).then(() => {
   this.router.navigate([currentUrl]);
   });
 }
Anthocyanin answered 12/1, 2021 at 5:2 Comment(1)
best solution, it's not touching angular mechanism and change it. solve it with a simple workaroundSacrilegious
A
6
import { DOCUMENT } from '@angular/common';
import { Component, Inject } from '@angular/core';

@Component({
  selector: 'app-refresh-banner-notification',
  templateUrl: './refresh-banner-notification.component.html',
  styleUrls: ['./refresh-banner-notification.component.scss']
})

export class RefreshBannerNotificationComponent {

  constructor(
    @Inject(DOCUMENT) private _document: Document
  ) {}

  refreshPage() {
    this._document.defaultView.location.reload();
  }
}
Annalist answered 19/1, 2020 at 21:40 Comment(0)
S
4

Writing this as 2021 (Angular 12 running). Read explanation or jump to end for straight answer.

All the answers on this thread and others didn't help me quite much because of unwanted behaviour. What I did instead is implemented a hack.

Some light on existing answers

Angular will reload page which means Page Component/Resolvers/Guards in specific way.

using this.router.onSameUrlNavigation = 'reload';

doesn't work most of the time because main purpose of it is to Re-enable Resolvers/Guards. Its mistaken for other meaning though.Also I didn't want to change this across as a global setting so nope!

Another way of window.location.reload() OR window.location.href=window.location.href is worst possible way as it violates SPA rules. Downloading all chunks again is very bad solution.

While below solution works, for my usecase it was routing twice, so dropped this as well

this.router.navigateByUrl('', { skipLocationChange: true }).then(() => {
   this.router.navigate(['/launchpad']);
});

Now the HACK / Solution

Why not tell angular its different route altogether, so reloading is taken care by Angular itself, it also covers guards, resolvers everything. For my usecase

In app-routing.module.ts I added same module with two different routes

one with '' empty route and one with say 'post-login'

  {
    path: '',
    loadChildren: () => import('./post-login/post-login.module').then((m) => m.PostLoginModule),
    canActivate: [AuthGuard],
  },
  {
    path: 'post-login',
    loadChildren: () => import('./post-login/post-login.module').then((m) => m.PostLoginModule),
    canActivate: [AuthGuard],
  }

Now inside wherever I want to reload the same page, Inject router: Router

and use simply like this

 this.router.navigateByUrl(this.router.url.includes('post-login') ? '' : 'post-login');

This reloads page with alternate additional 'post-login' in Url but its fine for my usecase. Hope it helps :)

Schizophrenia answered 13/10, 2021 at 7:19 Comment(1)
This means I can only reload one specific route, i.e. not applicable in all situations.Gaullist
R
3

Because it's the same component. You can either listen to route change by injecting the ActivatedRoute and reacting to changes of params and query params, or you can change the default RouteReuseStrategy, so that a component will be destroyed and re-rendered when the URL changes instead of re-used.

Ram answered 18/9, 2018 at 14:58 Comment(0)
L
2

With angular 11 you can just use this:

in route config add runGuardsAndResolvers: 'always'

const routes: Routes = [
  { path: '', component: Component, runGuardsAndResolvers: 'always' },
];

and this is your method to reload:

  reloadView(): void {
    this.router.navigated = false;
    this.router.navigate(['./'], { relativeTo: this.route });
  }

this will trigger any resolver on that config

Latty answered 22/1, 2021 at 13:39 Comment(1)
this.router.navigated = false; was what I was missing to get runGuardsAndResolvers: 'always' working as expected.Ranaerancagua
A
2

By this way we can preserve queryparams also

 onReloadPage() {
     this.router.routeReuseStrategy.shouldReuseRoute = () => false;
     this.router.onSameUrlNavigation = 'reload';
     this.router.navigate(['./'], { relativeTo: this.activatedRoute, queryParamsHandling: 'preserve' });
 }
Assure answered 3/3, 2021 at 16:42 Comment(0)
L
2

For child and main component, I have written the following code to reload the page

reloadCurrentRoute() {
    let currentUrl = this.router.url;
    this.router.navigateByUrl('/', {skipLocationChange: true}).then(() => {
        this.router.navigate([currentUrl]);
    });
}
Larger answered 20/2, 2022 at 7:50 Comment(0)
T
1

Setting shouldReuseRoute and onSameUrlNavigation properly on the router will force angular to reload when navigating on the same page, however as the router is a singleton, it might be relevant to set back its initial values after reloading the page.

This method below will backup and restore the router's settings to prevent side effects to occur. Please comment if you do have a cleaner solution to achieve the same.

class MyComponent {

constructor(private router: Router){}

public async reload(): Promise<boolean> {
    const router = this.router;
    const routeReuseStrategy = router.routeReuseStrategy.shouldReuseRoute;
    const onSameUrlNavigation = router.onSameUrlNavigation;
    try {
      router.routeReuseStrategy.shouldReuseRoute = () => false;
      router.onSameUrlNavigation = 'reload';
      return await router.navigateByUrl(router.url);
    } finally {
      router.routeReuseStrategy.shouldReuseRoute = routeReuseStrategy;
      router.onSameUrlNavigation = onSameUrlNavigation;
    }
  }
}
Tapir answered 11/10, 2021 at 11:23 Comment(0)
A
0

Here is the simple one

if (this.router && this.router.url === '/') { or your current page url e.g '/home' 
    window.location.reload();
  } else {
    this.router.navigate([url]);
  }
Administrative answered 15/4, 2020 at 7:5 Comment(0)
I
0

I believe Angular 6 has the BehaviorSubject object. My sample below is done using Angular 8 and will hopefully work for Angular 6 as well.

This method is a more "reactive" approach to the problem, and assumes you are using and are well versed in rxjs.

Assuming you are using an Observable in your parent component, the component that is used in your routing definition, then you should be able to just pulse the data stream pretty easily.

My example also assumes you are using a view model in your component like so...

vm$: Observable<IViewModel>;

And in the HTML like so...

<div *ngIf="(vm$ | async) as vm">

In your component file, add a BehaviorSubject instance...

private refreshBs: BehaviorSubject<number> = new BehaviorSubject<number>(0);

Then also add an action that can be invoked by a UI element...

  refresh() {
    this.refreshBs.next(1);
  }

Here's the UI snippet, a Material Bootstrap button...

<button mdbBtn color="primary" class="ml-1 waves-dark" type="button" outline="true"
                    (click)="refresh()" mdbWavesEffect>Refresh</button>

Then, in your ngOnIt function do something like this, keep in mind that my example is simplified a bit so that I don't have to provide a lot of code...

  ngOnInit() {

    this.vm$ = this.refreshBs.asObservable().pipe(
      switchMap(v => this.route.queryParamMap),
      map(qpm => qpm.get("value")),
      tap(v => console.log(`query param value: "${v}"`)),

      // simulate data load
      switchMap(v => of(v).pipe(
        delay(500),
        map(v => ({ items: [] }))
      )),
      
      catchError(e => of({ items: [], error: e }))
    );
    
  }
Illustrious answered 4/8, 2020 at 12:37 Comment(0)
T
0

See this stackblitz which use a RouteReuseStrategy in combination with the onSameUrlNavigation: 'reload' Router option.

This strategy ensures that angular will always re-render the components when navigating to what it considers the "same" route (which includes having different path and query parameters).

@Injectable()
export class MyStrategy extends RouteReuseStrategy {
   shouldDetach(route: ActivatedRouteSnapshot): boolean {
    return false;
  }
  store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {}
  shouldAttach(route: ActivatedRouteSnapshot): boolean {
    return false;
  }
  retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle|null {
    return null;
  }
  shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
    return false;
  }
}

const routes = [
  {path: '2', component: Empty2},
  {path: '', component: Empty},
];

@NgModule({
  imports:      [ BrowserModule, RouterModule.forRoot(routes, {onSameUrlNavigation: 'reload'}) ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ], 
  providers: [{provide: RouteReuseStrategy, useClass: MyStrategy}]
})
export class AppModule { }
Tolle answered 1/3, 2021 at 9:27 Comment(0)
T
-6
private router: Router

this.router.navigateByUrl(url)

It will redirect to any pages without data lost (even current page). Data will remain as is.

Talishatalisman answered 28/6, 2019 at 6:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.