Sto chiamando router.navigate
sulla stessa pagina con alcuni parametri della stringa di query. In questo caso, ngOnInit()
non chiama. È di default o devo aggiungere qualcos'altro?
Sto chiamando router.navigate
sulla stessa pagina con alcuni parametri della stringa di query. In questo caso, ngOnInit()
non chiama. È di default o devo aggiungere qualcos'altro?
Risposte:
Puoi iniettare il ActivatedRoute
e iscriverti aparams
constructor(route:ActivatedRoute) {
route.params.subscribe(val => {
// put the code from `ngOnInit` here
});
}
Il router distrugge e ricrea il componente solo quando naviga su un percorso diverso. Quando vengono aggiornati solo i parametri del percorso o i parametri della query ma il percorso è lo stesso, il componente non verrà distrutto e ricreato.
Un modo alternativo per forzare la ricreazione del componente consiste nell'usare una strategia di riutilizzo personalizzata. Vedi anche Angular2 router 2.0.0 non ricarica i componenti quando lo stesso URL viene caricato con parametri diversi? (non sembrano esserci ancora molte informazioni disponibili su come implementarlo)
È possibile modificare la strategia di riutilizzo sul router.
constructor(private router: Router) {
// override the route reuse strategy
this.router.routeReuseStrategy.shouldReuseRoute = function() {
return false;
};
}
onSameUrlNavigation: 'reload'
l'oggetto di configurazione in questo modo: RouterModule.forRoot(appRoutes, {onSameUrlNavigation: 'reload'})
. Tuttavia, non potrei parlare per altre versioni di Angular.
Ho usato quanto segue e ha funzionato.
onButtonClick() {
this.router.routeReuseStrategy.shouldReuseRoute = function () {
return false;
}
this.router.onSameUrlNavigation = 'reload';
this.router.navigate('/myroute', { queryParams: { index: 1 } });
}
navigate()
?
Probabilmente hai bisogno di ricaricare la pagina? Questa è la mia soluzione: ho cambiato il @NgModule (nel file app-routing.module.ts nel mio caso):
@NgModule({
imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: 'reload'})] })
Sul tuo metodo di navigazione,
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.router.onSameUrlNavigation = 'reload';
this.router.navigate(['/document'], {queryParams: {"search": currentSearch}});
Ho avuto lo stesso problema, inoltre ho ricevuto l'avviso:
did you forget to call `ngZone.run()`
Questo sito ha fornito la migliore soluzione:
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]));
}
Questo problema deriva probabilmente dal fatto che non stai terminando le tue iscrizioni usando ngOnDestroy. Ecco come fare.
Porta la seguente importazione dell'abbonamento rxjs.
import { Subscription } from 'rxjs/Subscription';
Aggiungi OnDestory alla tua importazione Angular Core.
import { Component, OnDestroy, OnInit } from '@angular/core';
Aggiungi OnDestory alla tua classe di esportazione.
export class DisplayComponent implements OnInit, OnDestroy {
Crea una proprietà oggetto con un valore di Sottoscrizione da rxjs nella tua classe di esportazione per ogni sottoscrizione sul componente.
myVariable: Subscription;
Imposta il valore dell'abbonamento su MyVariable: Subscriptions.
this.myVariable = this.rmanagerService.getRPDoc(books[i].books.id).subscribe(value => {});
Quindi, proprio sotto ngOninit, posizionare il gancio del ciclo di vita ngOnDestory () e inserire la dichiarazione di annullamento dell'iscrizione per la sottoscrizione. Se ne hai più, aggiungine altri
ngOnDestroy() {
this.myVariable.unsubscribe();
}
ngOnDestory
posto di ngOnDestroy
me stesso ;-)
Ecco una raccolta delle migliori idee in questa pagina con maggiori informazioni
Soluzione 1: utilizzare l'abbonamento a params:
Tutorial: https://angular-2-training-book.rangle.io/routing/routeparams#reading-route-parameters
Documenti: https://angular.io/api/router/ActivatedRoute#params
In ciascuno dei componenti di instradamento che utilizzano le variabili param includono quanto segue:
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();
}
}
Alcuni problemi comuni con questo codice sono che gli abbonamenti sono asincroni e possono essere più complicati da gestire. Inoltre non puoi dimenticare di annullare l'iscrizione a ngOnDestroy altrimenti possono accadere cose brutte.
La cosa buona è che questo è il modo più documentato e comune per gestire questo problema. C'è anche un miglioramento delle prestazioni in questo modo poiché stai riutilizzando il modello invece di distruggere e ricreare ogni volta che visiti una pagina.
Soluzione 2 - shouldReuseRoute / onSameUrlNavigation:
Documenti: https://angular.io/api/router/ExtraOptions#onSameUrlNavigation
Documenti: https://angular.io/api/router/RouteReuseStrategy#shouldReuseRoute
Documenti: https://angular.io/api/router/ActivatedRouteSnapshot#params
Trova dove RouterModule.forRoot
si trova nel tuo progetto (normalmente si trova in app-routing.module.ts o app.module.ts):
const routes: Routes = [
// ...
];
// ...
@NgModule({
imports: [RouterModule.forRoot(routes, {
onSameUrlNavigation: 'reload'
})],
exports: [RouterModule]
})
Quindi in AppComponent aggiungi quanto segue:
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;
};
// ...
}
// ...
}
Infine, nei tuoi componenti di routing ora puoi gestire le variabili param in questo modo:
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;
// ...
}
// ...
}
Problemi comuni con questa soluzione è che non è comune. Inoltre stai modificando il comportamento predefinito del framework Angular, in modo da poter incorrere in problemi in cui le persone normalmente non andrebbero incontro.
La cosa buona è che tutto il tuo codice è sincrono e più facile da capire.
Considera l'idea di spostare il codice che avevi in ngOnInit in ngAfterViewInit. Quest'ultimo sembra essere chiamato sulla navigazione del router e dovrebbe aiutarti in questo caso.
Quando vuoi usare il router, naviga sulla stessa pagina e vuoi chiamare ngOnInit (), quindi ti piace, ad es.
this.router.navigate (['category / list', category]) .then (() => window.location.reload ());