128

I am working on an Angular project. I'm struggling with refresh action in a component.

I would like to refresh the router's components on button click. I have refresh button when I click on it the component/router need to be refresh.

I tried window.location.reload() and location.reload() these two are not suitable for my need. Please help if anyone aware of it.

Gil Epshtain
  • 7,189
  • 7
  • 50
  • 74
Sreehari Ballampalli
  • 2,994
  • 3
  • 11
  • 19
  • Can you share your code in this question ? what you are tried. – Chandru Dec 14 '17 at 13:07
  • it's a complex code, it has N number of line of code, difficult to share – Sreehari Ballampalli Dec 14 '17 at 13:14
  • @Saurabh, normally it's not necesary reload a component. You can have a function (e.g. call "restart") and call the function in your button Refresh. If you need subscribe to change path, or another service, use the function ngOnInit -your component must extends OnInit-, not the constructor – Eliseo Dec 14 '17 at 20:17
  • This is what I did with Angular 9 https://stackoverflow.com/a/60909777/1072395 – Wlada Mar 29 '20 at 03:24

20 Answers20

149

After some research and modifying my code as below, the script worked for me. I just added the condition:

this.router.navigateByUrl('/RefreshComponent', { skipLocationChange: true }).then(() => {
    this.router.navigate(['Your actualComponent']);
}); 
Philipp Kief
  • 7,072
  • 4
  • 34
  • 42
Sreehari Ballampalli
  • 2,994
  • 3
  • 11
  • 19
  • 2
    I'm using this in an injectable service. I replaced `"your actualComponent"` with a variable. The variable is set is set to [`this.location.path()`](https://angular.io/api/common/Location#path) before the call to `navigateByUrl`. That way, no need to pass any parameters from calling component or duplicate/pass around routes. – Tewr Jan 09 '19 at 13:48
  • 7
    can you please explain what is 'RefrshComponent' and 'Your actualComponent'? – reverie_ss Jan 13 '19 at 15:59
  • 23
    Most everyone will be fine using `'/'` where `/RefrshComponent` is, and for `[Your actualComponent"]` you would just pass the url (and/or params) that you would like to reload such as `this.router.navigate(["/items"])`. This hack essentially redirects to the top URL, and then very quickly back to the intended URL which is unnoticeable to most users and appears to be the most elegant hack to achieve this simply. – sofly Feb 01 '19 at 23:04
  • Works like a charm! Thanks! – Ali Celebi Mar 20 '19 at 07:15
  • 5
    I agree this should definitely work... but it fails in my app (Angular 6). If I use `'/'` as my dummy route it goes (via `redirectTo`) to where my app-routing.module.ts redirects to on a path of `''` (empty string) and stops, not proceeding to the completion route in the `navigate()` call. If I use a non-existent string (e.g. `/foo`) as my dummy route, it goes (via `redirectTo`) to where my app-routing.module.ts redirects for `**` (everything else) and again stops, not going to the real route. Curiously, the URL bar DOES change to the real route. Any thoughts on what is different here? – Michael Sorens May 10 '19 at 03:08
  • 1
    this can cause an infinite redirection loop if not used carefully – Tomas Katz Jul 28 '19 at 11:49
  • 1
    It works like a charm. I just tested in Angular 8. Why this may create infinite redirection loop @TomasKatz? – allucardster Oct 24 '19 at 07:02
  • How do you use this without a loop? You can only call this manually if you know if it is the first load or not... – Jonathan Mar 25 '20 at 05:21
  • What about 'this' keyword when this.router.navigate(['Your actualComponent']).then... is finished ? What context is used ? – mtnp Jun 28 '21 at 12:51
  • Thanks! In my case, this helped me to reload the table with angular-datatable without the need to apply the rerender method that is explained in its documentation and the code is very dirty. – nicpas Feb 21 '22 at 02:23
92

Use the this.ngOnInit(); to reload the same component instead reloading the entire page!!

DeleteEmployee(id:number)
  {
    this.employeeService.deleteEmployee(id)
    .subscribe( 
      (data) =>{
        console.log(data);

        this.ngOnInit();

      }),
      err => {
        console.log("Error");
      }   
  }
Shinoy Babu
  • 1,373
  • 1
  • 11
  • 11
  • 11
    While this might answer the authors question, it lacks some explaining words and/or links to documentation. Raw code snippets are not very helpful without some phrases around them. You may also find [how to write a good answer](https://stackoverflow.com/help/how-to-answer) very helpful. Please edit your answer. – hellow Nov 02 '18 at 07:44
  • 2
    This is a better input than the selected answer but it lacks explanation. In my specific case I had to refresh a child component. In that case there are several way but the recommended are using a service or broadcasting an event from the parent to the child. – Claudio May 07 '19 at 11:27
  • 7
    Agreed, this only works if you want to refresh the component from within the component - if you are dealing with child/external components this.ngOnInit() will not work – astro8891 May 14 '19 at 03:20
  • 5
    Even though it works for component, it doesn't reset form validators. – Vicky Gonsalves Jul 16 '19 at 08:08
  • 4
    Works perfect, thank you. And regarding the explanation AFAIC, the code says it all. – Marton Tatai Mar 11 '20 at 10:42
  • 1
    great, it is exactly what i needed. thanks~ – Wayne Wei Jun 21 '21 at 11:11
  • ngOnInit is a lifecycle method called by angular. you shouldn't call it yourself. if there's some logic from ngOnInit that you want to execute again, just move it into a method and call that method. – LarryP Mar 14 '22 at 07:49
29

Adding this to code to the required component's constructor worked for me.

this.router.routeReuseStrategy.shouldReuseRoute = function () {
  return 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;
  }
});

Make sure to unsubscribe from this mySubscription in ngOnDestroy().

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

Refer to this thread for more details - https://github.com/angular/angular/issues/13831

Amir Fawzy
  • 448
  • 6
  • 12
sankar
  • 717
  • 7
  • 10
21

Fortunately, if you are using Angular 5.1+, you do not need to implement a hack anymore as native support has been added. You just need to set onSameUrlNavigation to 'reload' in the RouterModule options :

@ngModule({
 imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: ‘reload’})],
 exports: [RouterModule],
 })

More information can be found here: https://medium.com/engineering-on-the-incline/reloading-current-route-on-click-angular-5-1a1bfc740ab2

Lucian Moldovan
  • 527
  • 4
  • 6
  • You can use `router.onSameUrlNavigation = 'reload'` property of injected Router, too. – 0zkr PM Dec 12 '18 at 03:23
  • 4
    Using angular 6, to me this made no difference, that is, component did not reload. The accepted answer works however. – Tewr Jan 09 '19 at 13:42
  • 5
    Although not entirely clear in the docs, `onSameUrlNavigation` is intended to reinvoke Guards/Resolvers, and not to reload already routed components. See https://github.com/angular/angular/issues/21115 for more on this. This solution will work for larger more complex applications using Guards/Resolvers but will fail for simple examples. – sofly Feb 01 '19 at 23:07
  • 2
    yes, onSameUrlNavigation will fire the navigation events again, but this does not reload the component – Paul Story Sep 27 '19 at 19:54
  • yes! this solution is working. May be you could mention more detail in you answer. – Abhishek Singh Jun 16 '21 at 06:15
11

this is little bit out of box and I dont know whether this helps you or not but have yo tried

this.ngOnInit();

its a function so whatever code you have in it will be recalled just like a refresh.

9

One more way without explicit route:

async reload(url: string): Promise<boolean> {
  await this.router.navigateByUrl('.', { skipLocationChange: true });
  return this.router.navigateByUrl(url);
}
Felix
  • 3,223
  • 2
  • 33
  • 57
7

Just follow the below steps:

  1. add {onSameUrlNavigation: 'reload'} as below in your app-routing.modules.ts

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

  1. add this.router.routeReuseStrategy.shouldReuseRoute = () => false as below in you component ts file constructor:
constructor(private router: Router) {
      this.router.routeReuseStrategy.shouldReuseRoute = () => false;
  }
  1. Now click the button and call ajax server call, get the desired data from server and replace your global variable in TS file with new data.
  2. call this.router.navigate([/sameRoute]); in the last. replace sameRoute with your route url.

  3. make sure to return false at the end in your refresh button's onClick method, otherwise it will lead to main routing page instead of same page reload.

    These steps will reload your page. :)

For more details: https://medium.com/engineering-on-the-incline/reloading-current-route-on-click-angular-5-1a1bfc740ab2

I am using Angular 12.

Abhishek Singh
  • 1,087
  • 1
  • 19
  • 39
  • This is the correct answer for me thanks god. You can change 4 with this.router.navigateByUrl(this.router.url); – user721730 Jan 17 '22 at 12:43
5

This can be achieved via a hack, Navigate to some sample component and then navigate to the component that you want to reload.

this.router.navigateByUrl('/SampleComponent', { skipLocationChange: true });
this.router.navigate(["yourLandingComponent"]);
Sajeetharan
  • 203,447
  • 57
  • 330
  • 376
3

There are problems with some of the answers before:

  1. one should not call lifecycle methods such as ngOnInit() directly.
  2. re-navigating to some URL is a sub-optimal solution, especially if the component you are dynamically loading is only a small part of a big page

This worked for me (I don't know if it is recommendable or optimal)

  1. In the component to be dynamically loaded, add a public reference to the ChangeDetectorRef.
  2. I assume that the dynamically loaded data has some input data, ("tags" in the example), which is updated after the fact and is creating rendering problems.
  @Input()
  tags: string[] = [];

  constructor(public changeDetector: ChangeDetectorRef )
  1. In the parent component doing the dynamic loading, after having created the child component dynamically and maybe set some data to it, call the created instance's changeDetector.markForCheck() as follows:
  constructor(private vcrf: ViewContainerRef, private cfr: ComponentFactoryResolver, private elementRef: ElementRef) {
  }

  public loadComponent(): void {

    const componentFactory = this.cfr.resolveComponentFactory(TagsListComponent);
    const component = this.container.createComponent(componentFactory);
    component.instance.tags = /* whatever data we want to pass */;
    component.instance.changeDetector.markForCheck();
    ...

loadComponent() is a custom function that could be called, for example, once the parent page scrolls to some position in the parent component, indicating that the dynamic component should be shown.

raaaay
  • 433
  • 7
  • 12
2

In my application i have component and all data is coming from API which i am calling in Component's constructor. There is button by which i am updating my page data. on button click i have save data in back end and refresh data. So to reload/refresh the component - as per my requirement - is only to refresh the data. if this is also your requirement then use the same code written in constructor of component.

Bh00shan
  • 330
  • 4
  • 17
2

Just change the routeReuseStrategy from the angular Router:

this._router.routeReuseStrategy.shouldReuseRoute = function () {
      return false;
    };

Set the routerproperty "navigated" to false:

this._router.navigated = false;

Then navigate to your component:

this._router.navigate(['routeToYourComponent'])

After that reinstate the old/default routeReuseStrategy:

this._router.routeReuseStrategy.shouldReuseRoute = function (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
          return future.routeConfig === curr.routeConfig;

You can also make a service out of this:

@Injectable({
  providedIn: 'root'
})
export class RouterService {

  constructor(
    private _activatedRoute: ActivatedRoute,
    private _router: Router
  ) { }

  reuseRoutes(reuse: boolean) {
    if (!reuse) {
      this._router.routeReuseStrategy.shouldReuseRoute = function () {
        return false;
      };
    }
    if (reuse) {
      this._router.routeReuseStrategy.shouldReuseRoute = function (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
        return future.routeConfig === curr.routeConfig;
      };
    }
  }

  async refreshPage(url?: string) {
    this._router.routeReuseStrategy.shouldReuseRoute = function () {
      return false;
    };

    this._router.navigated = false;

    url ? await this._router.navigate([url]) : await this._router.navigate([], { relativeTo: this._activatedRoute });

    this._router.routeReuseStrategy.shouldReuseRoute = function (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
      return future.routeConfig === curr.routeConfig;
    };
  }
}
karel
  • 4,637
  • 41
  • 42
  • 47
1

kdo

// reload page hack methode

push(uri: string) {
    this.location.replaceState(uri) // force replace and no show change
    await this.router.navigate([uri, { "refresh": (new Date).getTime() }]);
    this.location.replaceState(uri) // replace
  }
1
constructor(private router:Router, private route:ActivatedRoute ) { 
}

onReload(){
 this.router.navigate(['/servers'],{relativeTo:this.route})
}
Mohammad Sayeed
  • 1,845
  • 1
  • 15
  • 27
1

calling ngOnInit() does not work for my complicated component, I end up using this

reloadCurrentRoute() {
    let currentUrl = this.router.url;
    this.router.navigateByUrl('/', {skipLocationChange: true}).then(() => {
        this.router.navigate([currentUrl]);
    });
}
Suraj Rao
  • 28,850
  • 10
  • 94
  • 99
Feng Zhang
  • 1,232
  • 1
  • 12
  • 18
0

just do this : (for angular 9)

import { Inject } from '@angular/core';    
import { DOCUMENT } from '@angular/common';

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

someMethode(){ this.document.location.reload(); }
Reza Piri
  • 77
  • 1
  • 7
    Please read the OPs comment, refreshing the whole page is not an option for him, it defeats the purpose of having angular in the first place – ihorbond May 04 '20 at 16:43
  • 1
    The question ask for reload component only not whole page. – Santosh Jul 28 '20 at 08:22
0

html file

<a (click)= "getcoursedetails(obj.Id)" routerLinkActive="active" class="btn btn-danger">Read more...</a>

ts file

  getcoursedetails(id)
  { 
  this._route.navigateByUrl('/RefreshComponent', { skipLocationChange: true }).then(() => {
    this._route.navigate(["course",id]);
  }); 
Suraj Rao
  • 28,850
  • 10
  • 94
  • 99
0

router.navigate['/path'] will only takes you to the specified path
use router.navigateByUrl('/path')
it reloads the whole page

Harpreet Singh
  • 329
  • 3
  • 8
0

reload () { this.ngOnInit(); }

Anis KCHAOU
  • 445
  • 1
  • 7
  • 10
0

In my case I needed to reload specific routes (not all in the application), so adding the global setting {onSameUrlNavigation: 'reload'} had no effect, while this.router.routeReuseStrategy.shouldReuseRoute = () => false in the component works but modifies the global settings of the router.

The solution was to save the original router configuration to a variable before changing it in the component's constructor as indicated @abhishek-singh by the first answer of the problem.

private routeReuseStrategy:any;

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

And when exiting the path, remap the original configuration using the OnDestroy hook.

   public ngOnDestroy():void
   {
     this.router.routeReuseStrategy.shouldReuseRoute = this.routeReuseStrategy;
   }
Juan Castillo
  • 41
  • 1
  • 3
-4

Other way to refresh (hard way) a page in angular 2 like this it's look like f5

import { Location } from '@angular/common';

constructor(private location: Location) {}

pageRefresh() {
   location.reload();
}
chirag sorathiya
  • 1,143
  • 7
  • 28