Router Navigate does not call ngOnInit when same page

AngularNavigateurlNgoninit

Angular Problem Overview


I am calling router.navigate on same page with some query string parameters. In this case, ngOnInit() does not call. Is it by default or do I need to add anything else ?

Angular Solutions


Solution 1 - Angular

You can inject the ActivatedRoute and subscribe to params

constructor(route:ActivatedRoute) {
  route.params.subscribe(val => {
    // put the code from `ngOnInit` here
  });
}

The router only destroys and recreates the component when it navigates to a different route. When only route params or query params are updated but the route is the same, the component won't be destroyed and recreated.

An alternative way to force the component to be recreated is to use a custom reuse strategy. See also https://stackoverflow.com/questions/39533291/angular2-router-2-0-0-not-reloading-components-when-same-url-loaded-with-differe/39533351#39533351 (there doesn't seem to be much information available yet how to implement it)

Solution 2 - Angular

You could adjust the reuseStrategy on the Router.

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

Solution 3 - Angular

Angular 9

I have used the following and it worked.

onButtonClick() {
    this.router.routeReuseStrategy.shouldReuseRoute = function () {
        return false;
    }
    this.router.onSameUrlNavigation = 'reload';
    this.router.navigate('/myroute', { queryParams: { index: 1 } });
}

Solution 4 - Angular

Do you probably need reloading page? This is my solution: I've changed the @NgModule (in app-routing.module.ts file in my case) :

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

Solution 5 - Angular

On your navigation method,

this.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.router.onSameUrlNavigation = 'reload';
this.router.navigate(['/document'], {queryParams: {"search": currentSearch}});

Solution 6 - Angular

Here is a collection of the best ideas on this page with more information

Solution 1 - Use params subscription:

Tutorial: https://angular-2-training-book.rangle.io/routing/routeparams#reading-route-parameters

Docs: https://angular.io/api/router/ActivatedRoute#params

In each of your routing components that use param variables include the following:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';

// ...

@Component({
    // ...
})
export class MyComponent implements OnInit, OnDestroy {
    paramsSub: Subscription;

    // ...

    constructor(activeRoute: ActivatedRoute) {
    
    }

    public ngOnInit(): void {
        // ...
        this.paramsSub = this.activeRoute.params.subscribe(val => {
            // Handle param values here
        });

        // ...
    }

    // ...

    public ngOnDestroy(): void {
        // Prevent memory leaks
        this.paramsSub.unsubscribe();
    }
}

Some common issues with this code is that subscriptions are asynchronous and can be trickier to deal with. Also you can't forget to unsubscribe on ngOnDestroy or else bad things can happen.

Good thing is that this is the most documented and common way to handle this problem. There's also a performance improvement doing it this way since you are reusing the template instead of destroying and recreating each time you visit a page.

Solution 2 - shouldReuseRoute / onSameUrlNavigation:

Docs: https://angular.io/api/router/ExtraOptions#onSameUrlNavigation

Docs: https://angular.io/api/router/RouteReuseStrategy#shouldReuseRoute

Docs: https://angular.io/api/router/ActivatedRouteSnapshot#params

Find where RouterModule.forRoot is located in your project (normally found in app-routing.module.ts or app.module.ts):

const routes: Routes = [
   // ...
];

// ...

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

Then in AppComponent add the following:

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

// ...
@Component({
    // ...
})
export class AppComponent implements OnInit {
    constructor(private router: Router) {
    }

    ngOnInit() {
        // Allows for ngOnInit to be called on routing to the same routing Component since we will never reuse a route
        this.router.routeReuseStrategy.shouldReuseRoute = function() {
            return false;
        };

        // ...
    }

    // ...
}

Last, in your routing components you can now handle param variables like this:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

// ...

@Component({
    // ...
})
export class MyComponent implements OnInit {
    // ...

    constructor(activeRoute: ActivatedRoute) {
    
    }

    public ngOnInit(): void {
        // Handle params
        const params = +this.activeRoute.snapshot.params;
        
        // ...
    }

    // ...
}

Common issues with this solution is that it isn't common. Also you are changing the default behavior of the Angular framework, so you can run into issues people wouldn't normally run into.

Good thing is that all your code is synchronous and easier to understand.

Solution 7 - Angular

I've had the same issue, additionally I got the warning:

>none >did you forget to call `ngZone.run()` >

This site provided the best solution:

import { Router } from '@angular/router';
import { NgZone } from '@angular/core';

...

  constructor(
    private ngZone:NgZone,
    private _router: Router
  ){ }

  redirect(to) {
    // call with ngZone, so that ngOnOnit of component is called
    this.ngZone.run(()=>this._router.navigate([to]));
  }

Solution 8 - Angular

NgOnInit would be called once when an instance is created. For the same instance NgOnInit won't be called again. In order to call it it is necessary to destroy the created instance.

Solution 9 - Angular

This problem is likely coming from that fact that you are not terminating your subscriptions using ngOnDestroy. Here is how to get'ter done.

  1. Bring in the following rxjs subscription import. import { Subscription } from 'rxjs/Subscription';

  2. Add OnDestory to your Angular Core Import. import { Component, OnDestroy, OnInit } from '@angular/core';

  3. Add OnDestory to your export class. export class DisplayComponent implements OnInit, OnDestroy {

  4. Create a object property with a value of Subscription from rxjs under your export class for each subscription on the component. myVariable: Subscription;

  5. Set the value of your subscription to MyVariable: Subscriptions. this.myVariable = this.rmanagerService.getRPDoc(books[i].books.id).subscribe(value => {});

  6. Then right below ngOninit place the ngOnDestory() life cycle hook and put in your unsubscribe statement for your subscription. If you have multiple, add more ngOnDestroy() { this.myVariable.unsubscribe(); }

Solution 10 - Angular

Create a different path for the same component in the routes array .

const routes : Routes = [ { path : "app", component: MyComponent }, { path: "app-reload", component: MyComponent }];

If the current URL is "app" then navigate using "app-reload" and vice versa.

Solution 11 - Angular

This is the best solution for Router Navigate does not call the ngOnInit function when same page

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

Solution 12 - Angular

// this code is for redirecting to the dashboard page with calling ngOnInIt
    this.router.routeReuseStrategy.shouldReuseRoute = () => false;
    this.router.onSameUrlNavigation = 'reload';
    this.router.navigate(['./dashboard']);

this should works and should only used for special cases. When you dont have to navigate much after redirection you can use this.otherwise this will messed up some times. Note that you can always make the 'routeReuseStrategy' to true when you needed.

Solution 13 - Angular

Consider moving the code you had in ngOnInit into ngAfterViewInit. The latter seems to be called on router navigation and should help you in this case.

Solution 14 - Angular

When you want to router navigate on the same page and want to call ngOnInit(), so you do like that e.g,

this.router.navigate(['category/list', category]) .then(() => window.location.reload());

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJeeten ParmarView Question on Stackoverflow
Solution 1 - AngularGünter ZöchbauerView Answer on Stackoverflow
Solution 2 - AngularPascalView Answer on Stackoverflow
Solution 3 - AngularGuru CseView Answer on Stackoverflow
Solution 4 - AngularDionis OrosView Answer on Stackoverflow
Solution 5 - AngularDhwanil PatelView Answer on Stackoverflow
Solution 6 - AngularMark ThompsonView Answer on Stackoverflow
Solution 7 - AngularXnyXnoView Answer on Stackoverflow
Solution 8 - AngularNikhil ShahView Answer on Stackoverflow
Solution 9 - AngularSteve KlockView Answer on Stackoverflow
Solution 10 - AngularS AView Answer on Stackoverflow
Solution 11 - AngularSuresh Kumar chirukuriView Answer on Stackoverflow
Solution 12 - AngularMd omer arafatView Answer on Stackoverflow
Solution 13 - AngularManoj AmalrajView Answer on Stackoverflow
Solution 14 - AngularDeepak MaliView Answer on Stackoverflow