Router Navigate ruft ngOnInit nicht auf derselben Seite auf

86

Ich rufe router.navigateauf derselben Seite mit einigen Abfragezeichenfolgenparametern auf. In diesem Fall ngOnInit()ruft nicht an. Ist es standardmäßig oder muss ich noch etwas hinzufügen?

Jeeten Parmar
quelle

Antworten:

136

Sie können das injizieren ActivatedRouteund abonnierenparams

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

Der Router zerstört und erstellt die Komponente nur neu, wenn er zu einer anderen Route navigiert. Wenn nur Routenparameter oder Abfrageparameter aktualisiert werden, die Route jedoch dieselbe ist, wird die Komponente nicht zerstört und neu erstellt.

Eine alternative Möglichkeit, die Neuerstellung der Komponente zu erzwingen, ist die Verwendung einer benutzerdefinierten Wiederverwendungsstrategie. Siehe auch Angular2 Router 2.0.0 lädt keine Komponenten neu, wenn dieselbe URL mit unterschiedlichen Parametern geladen wurde. (Es scheinen noch nicht viele Informationen verfügbar zu sein, wie man es implementiert)

Günter Zöchbauer
quelle
1
Dieses Abonnement funktioniert nicht. Es wird nur auf init
ausgelöst
@OsandaWedamulla, das dann spezifisch für Ihren Code ist. Ohne weitere Details schwer zu sagen
Günter Zöchbauer
1
Müssen Sie sich nicht auch davon abmelden oder erfolgt dies automatisch?
rain01
1
@ rain01 Als Faustregel gilt, dass Sie sich in Ihrer cpde explizit abmelden sollten, wenn Sie sich explizit angemeldet haben. Wenn Ihre Stammkomponente den oben genannten Code enthält, ist das Abbestellen überflüssig, da die Lebensdauer der Stammkomponente normalerweise der Lebensdauer der gesamten Angular-App entspricht.
Günter Zöchbauer
101

Sie können die reuseStrategy auf dem Router anpassen.

constructor(private router: Router) {
    // override the route reuse strategy
    this.router.routeReuseStrategy.shouldReuseRoute = function() {
        return false;
    };
}
Pascal
quelle
2
Dadurch wird das ngInit jeder Komponente auf der Seite initiiert.
jforjs
2
Nun, @Pascal, Sie haben mich gezwungen, mich bei SO anzumelden, um Ihre Antwort zu verbessern. Ich würde hinzufügen, dass Sie in Angular 6 auch onSameUrlNavigation: 'reload'das Konfigurationsobjekt wie folgt hinzufügen müssen : RouterModule.forRoot(appRoutes, {onSameUrlNavigation: 'reload'}). Kann aber nicht für andere Angular-Versionen sprechen.
Hildy
1
@Hildy, ich war gezwungen das gleiche zu tun :) Danke @Pascal! Wenn Sie Lambda bevorzugen, können Sie dies tun.router.routeReuseStrategy.shouldReuseRoute = () => false;
Nick
1
@ Swaprks Ich habe eine routing.module.ts erstellt und den Code als diesen Konstruktor platziert
Pascal
1
@ Swaprks .. Ich habe ein ähnliches Problem und möchte Ihre Antwort oben ausprobieren. Aber als Anfänger auf diesem Gebiet sagt es mir nicht viel. Genau wo im Code soll ich dieses Codestück platzieren? Soll ich irgendetwas im Code-Snippet ändern (zB ´function () ´)? Wenn Sie eine neue Datei mit dem Namen routing.module.ts erstellt haben, wie soll sie dann mit anderen Dateien interagieren? Es gibt auch eine Datei namens app-routing.module.ts, die automatisch erstellt wird.
EDN
21

Winkel 9

Ich habe folgendes verwendet und es hat funktioniert.

onButtonClick() {
    this.router.routeReuseStrategy.shouldReuseRoute = function () {
        return false;
    }
    this.router.onSameUrlNavigation = 'reload';
    this.router.navigate('/myroute', { queryParams: { index: 1 } });
}
Guru Cse
quelle
1
Verwenden Sie außerdem Lambda anstelle von oben. This.router.routeReuseStrategy.shouldReuseRoute = () => false;
Dhwanil Patel
Arbeitet in Angular 8.
Kishan Vaishnav
2
Würde dies das Router-Verhalten in der gesamten Anwendung ändern oder nur einmal für diese bestimmte Funktion auslösen navigate()?
Halfist
8

Benötigen Sie wahrscheinlich eine Seite zum Neuladen? Dies ist meine Lösung: Ich habe das @ NgModule geändert ( in meinem Fall in der Datei app-routing.module.ts ):

@NgModule({
  imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: 'reload'})] })
Dionis Oros
quelle
Was sind die "Routen" hier?
Dhwanil Patel
@DhwanilPatel Ihre Angular App Routen. Zum Beispiel "const route: Routes = [{Pfad: 'Krisenzentrum', Komponente: CrisisListComponent}, {Pfad: 'Helden', Komponente: HeroListComponent},]" angle.io/guide/router#register-router-and -routen
Dionis Oros
1

NgOnInitwürde einmal aufgerufen, wenn eine Instanz erstellt wird. Für die gleiche Instanz NgOnInitwird nicht wieder aufgerufen. Um es aufzurufen, muss die erstellte Instanz zerstört werden.

Mikronyken
quelle
1

Auf Ihrer Navigationsmethode,

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

Ich hatte das gleiche Problem, zusätzlich bekam ich die Warnung:

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

Diese Seite bot die beste Lösung:

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]));
  }
XnyXno
quelle
In diesem Zusammenhang möchte ich wissen, wie Sie mit dem Problem umgehen können, wenn Sie die Seite einfach mit der neuen Route aktualisieren. In diesem Fall ist die NgZone-Warnung weiterhin vorhanden.
Siddhant
0

Dieses Problem ist wahrscheinlich darauf zurückzuführen, dass Sie Ihre Abonnements nicht mit ngOnDestroy kündigen. Hier erfahren Sie, wie Sie es schaffen.

  1. Bringen Sie den folgenden rxjs-Abonnementimport mit. import { Subscription } from 'rxjs/Subscription';

  2. Fügen Sie Ihrem Angular Core-Import OnDestory hinzu. import { Component, OnDestroy, OnInit } from '@angular/core';

  3. Fügen Sie Ihrer Exportklasse OnDestory hinzu. export class DisplayComponent implements OnInit, OnDestroy {

  4. Erstellen Sie für jedes Abonnement der Komponente eine Objekteigenschaft mit dem Wert Subscription von rxjs unter Ihrer Exportklasse. myVariable: Subscription;

  5. Stellen Sie den Wert Ihres Abonnements auf MyVariable: Subscriptions ein. this.myVariable = this.rmanagerService.getRPDoc(books[i].books.id).subscribe(value => {});

  6. Platzieren Sie dann direkt unter ngOninit den Lebenszyklus-Hook ngOnDestory () und geben Sie Ihre Abmeldeerklärung für Ihr Abonnement ein. Wenn Sie mehrere haben, fügen Sie weitere hinzu ngOnDestroy() { this.myVariable.unsubscribe(); }

Steve Klock
quelle
Ich schreibe weiter ngOnDestoryanstatt ngOnDestroymich selbst
;-)
0

Erstellen Sie einen anderen Pfad für dieselbe Komponente im Routenarray.

const route: Routes = [{Pfad: "App", Komponente: MyComponent}, {Pfad: "App-Reload", Komponente: MyComponent}];

Wenn die aktuelle URL "App" lautet, navigieren Sie mit "App-Reload" und umgekehrt.

SA
quelle
0

Hier finden Sie eine Sammlung der besten Ideen auf dieser Seite mit weiteren Informationen

Lösung 1 - Verwenden Sie das params-Abonnement:

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

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

In jeder Ihrer Routing-Komponenten, die Parametervariablen verwenden, ist Folgendes enthalten:

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();
    }
}

Einige häufige Probleme mit diesem Code sind, dass Abonnements asynchron sind und schwieriger zu handhaben sind. Sie können auch nicht vergessen, sich bei ngOnDestroy abzumelden, da sonst schlimme Dinge passieren können.

Gut ist, dass dies der am besten dokumentierte und gebräuchlichste Weg ist, um dieses Problem zu lösen. Auf diese Weise wird auch die Leistung verbessert, da Sie die Vorlage wiederverwenden, anstatt sie bei jedem Besuch einer Seite zu zerstören und neu zu erstellen.

Lösung 2 - shouldReuseRoute / onSameUrlNavigation:

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

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

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

Finden Sie heraus, wo RouterModule.forRootsich Ihr Projekt befindet (normalerweise in app-routing.module.ts oder app.module.ts):

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

// ...

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

Fügen Sie dann in AppComponent Folgendes hinzu:

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;
        };

        // ...
    }

    // ...
}

Zuletzt können Sie in Ihren Routing-Komponenten jetzt folgende Parametervariablen verarbeiten:

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;

        // ...
    }

    // ...
}

Häufige Probleme mit dieser Lösung sind, dass es nicht häufig ist. Außerdem ändern Sie das Standardverhalten des Angular-Frameworks, sodass Sie auf Probleme stoßen können, auf die Menschen normalerweise nicht stoßen würden.

Gut ist, dass Ihr gesamter Code synchron und leichter zu verstehen ist.

Mark Thompson
quelle
-1

Verschieben Sie den Code, den Sie in ngOnInit hatten, in ngAfterViewInit. Letzteres scheint in der Routernavigation aufgerufen zu werden und sollte Ihnen in diesem Fall helfen.

Manoj Amalraj
quelle
3
das passiert nicht wirklich
nadav
-7

Wenn Sie mit dem Router auf derselben Seite navigieren und ngOnInit () aufrufen möchten, gefällt Ihnen dies z.

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

Deepak Mali
quelle