J'utilise angular 2 avec la stratégie de hashlocation.
Le composant est chargé avec cette route:
"departments/:id/employees"
Jusqu'ici tout va bien.
Après avoir effectué avec succès une sauvegarde par lots de plusieurs lignes de table modifiées, je souhaite recharger l'URL de la route actuelle via:
this.router.navigate([`departments/${this.id}/employees`]);
Mais rien ne se passe, pourquoi?
Si votre browse () ne modifie pas l'URL déjà affichée dans la barre d'adresse de votre navigateur, le routeur n'a rien à faire. Ce n'est pas le travail du routeur d'actualiser les données. Si vous souhaitez actualiser les données, créez un service injecté dans le composant et appelez la fonction de chargement sur le service. Si les nouvelles données doivent être récupérées, la vue sera mise à jour via des liaisons.
J'ai trouvé cette solution de contournement sur une demande de fonctionnalité GitHub pour Angular:
this._router.routeReuseStrategy.shouldReuseRoute = function(){
return false;
};
this._router.events.subscribe((evt) => {
if (evt instanceof NavigationEnd) {
this._router.navigated = false;
window.scrollTo(0, 0);
}
});
J'ai essayé d'ajouter ceci à ma fonction app.component.ts ngOnInit
, et cela a fonctionné. Tous les autres clics sur le même lien rechargent maintenant la component
et les données.
Lien vers la demande de fonctionnalité originale de GitHub
Le crédit va à mihaicux2 sur GitHub.
J'ai testé cela sur la version 4.0.0-rc.3
avec import { Router, NavigationEnd } from '@angular/router';
Ceci peut maintenant être effectué dans Angular 5.1 à l'aide de la propriété onSameUrlNavigation
de la configuration du routeur.
J'ai ajouté un blog expliquant comment mais ici l'essentiel est le suivant
Dans la configuration de votre routeur, activez l’option onSameUrlNavigation
en la configurant sur 'reload'
. Le routeur déclenche un cycle d'événements lorsque vous essayez de naviguer vers un itinéraire déjà actif.
@ngModule({
imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: 'reload'})],
exports: [RouterModule],
})
Dans vos définitions de route, définissez runGuardsAndResolvers
sur always
. Cela indiquera au routeur de toujours lancer les cycles des gardes et des résolveurs, en déclenchant les événements associés.
export const routes: Routes = [
{
path: 'invites',
component: InviteComponent,
children: [
{
path: '',
loadChildren: './pages/invites/invites.module#InvitesModule',
},
],
canActivate: [AuthenticationGuard],
runGuardsAndResolvers: 'always',
}
]
Enfin, dans chaque composant pour lequel vous souhaitez activer le rechargement, vous devez gérer les événements. Cela peut être fait en important le routeur, en liant les événements et en invoquant une méthode d'initialisation qui réinitialise l'état de votre composant et, si nécessaire, en récupérant les données.
export class InviteComponent implements OnInit, OnDestroy {
navigationSubscription;
constructor(
// … your declarations here
private router: Router,
) {
// subscribe to the router events. Store the subscription so we can
// unsubscribe later.
this.navigationSubscription = this.router.events.subscribe((e: any) => {
// If it is a NavigationEnd event re-initalise the component
if (e instanceof NavigationEnd) {
this.initialiseInvites();
}
});
}
initialiseInvites() {
// Set default values and re-fetch any data you need.
}
ngOnDestroy() {
if (this.navigationSubscription) {
this.navigationSubscription.unsubscribe();
}
}
}
Avec toutes ces étapes en place, le rechargement de route doit être activé.
Créez une fonction dans le contrôleur qui redirige comme il se doit l'itinéraire prévu
redirectTo(uri:string){
this.router.navigateByUrl('/DummyComponent', {skipLocationChange: true}).then(()=>
this.router.navigate([uri]));}
puis utilisez-le comme ça
this.redirectTo('//place your uri here');
cette fonction redirigera vers un itinéraire factice et reviendra rapidement à l'itinéraire de destination sans que l'utilisateur ne s'en rende compte.
Petit problème: utilisez le même chemin avec des paramètres factices. Par exemple-
refresh(){
this.router.navigate(["/same/route/path?refresh=1"]);
}
bidon de recharge angulaire 2-4
Pour moi, utiliser cette méthode dans un composant racine (composant présent sur n'importe quelle route) fonctionne:
onRefresh() {
this.router.routeReuseStrategy.shouldReuseRoute = function(){return false;};
let currentUrl = this.router.url + '?';
this.router.navigateByUrl(currentUrl)
.then(() => {
this.router.navigated = false;
this.router.navigate([this.router.url]);
});
}
La page de rechargement de param change ne se produira pas. C'est vraiment une bonne fonctionnalité. Il n'est pas nécessaire de recharger la page, mais nous devrions changer la valeur du composant. La méthode paramChange fera appel au changement d'URL. Donc, nous pouvons mettre à jour les données du composant
/product/: id / details
import { ActivatedRoute, Params, Router } from ‘@angular/router’;
export class ProductDetailsComponent implements OnInit {
constructor(private route: ActivatedRoute, private router: Router) {
this.route.params.subscribe(params => {
this.paramsChange(params.id);
});
}
// Call this method on page change
ngOnInit() {
}
// Call this method on change of the param
paramsChange(id) {
}
Trouvez une solution simple et rapide qui ne nécessite pas de bricoler avec le fonctionnement interne de Angular:
En gros: créez simplement un autre itinéraire avec le même module de destination et basculez simplement entre eux:
const routes: Routes = [
{
path: 'gesuch',
loadChildren: './sections/gesuch/gesuch.module#GesuchModule'
},
{
path: 'gesuch-neu',
loadChildren: './sections/gesuch/gesuch.module#GesuchModule'
}
];
Et voici le menu de tous les jours:
<ul class="navigation">
<li routerLink="/gesuch-neu" *ngIf="'gesuch' === getSection()">Gesuch</li>
<li routerLink="/gesuch" *ngIf="'gesuch' !== getSection()">Gesuch</li>
</ul>
J'espère que ça aide :)
Cela fonctionne pour moi comme un charme
this.router.navigateByUrl('/', {skipLocationChange: true}).then(()=>
this.router.navigate([<route>]));
Pour moi, le codage en dur avec
this.router.routeReuseStrategy.shouldReuseRoute = function() {
return false;
// or
return true;
};
Il existe différentes approches pour actualiser l'itinéraire actuel
Changer le comportement du routeur (Depuis Angular 5.1) Définissez les routeurs surSameUrlNavigation sur 'recharger'. Ceci émettra les événements de routeur sur la même navigation d'URL.
Laissez le routeur intact
J'ai écrit une explication plus détaillée sous https://medium.com/@kevinkreuzer/refresh-current-route-in-angular-512a19d58f6e
J'espère que cela t'aides.
J'utilise setTimeout
et navigationByUrl
pour résoudre ce problème ... Et cela fonctionne très bien pour moi.
Il est redirigé vers une autre URL et vient à la place dans l'URL actuelle ...
setTimeout(() => {
this.router.navigateByUrl('/dashboard', {skipLocationChange: false}).then(() =>
this.router.navigate([route]));
}, 500)
implémentez OnInit et appelez ngOnInit () dans la méthode pour route.navigate ()
Voir un exemple:
export class Component implements OnInit {
constructor() { }
refresh() {
this.router.navigate(['same-route-here']);
this.ngOnInit(); }
ngOnInit () {
}
Dans mon cas:
const navigationExtras: NavigationExtras = {
queryParams: { 'param': val }
};
this.router.navigate([], navigationExtras);
fonctionne correctement
Résolution d'un scénario similaire en utilisant un composant factice et une route pour reload
, qui effectue en fait un redirect
. Cela ne couvre certainement pas tous les scénarios utilisateur mais a juste fonctionné pour mon scénario.
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Http } from '@angular/http';
@Component({
selector: 'reload',
template: `
<h1>Reloading...</h1>
`,
})
export class ReloadComponent implements OnInit{
constructor(private router: Router, private route: ActivatedRoute) {
}
ngOnInit() {
const url = this.route.snapshot.pathFromRoot.pop().url.map(u => u.path).join('/');
this.router.navigateByUrl(url);
}
}
Le routage est câblé pour attraper toutes les URL à l'aide d'un caractère générique:
import { RouterModule } from '@angular/router';
import { NgModule } from '@angular/core';
import { LoginViewComponent } from './views/login/login.component';
import { HomeViewComponent } from './views/home/home.component';
import { ReloadComponent } from './views/reload/reload.component';
@NgModule({
declarations: [
LoginViewComponent, HomeViewComponent, ReloadComponent
],
imports: [
RouterModule.forRoot([
{ path: 'login', component: LoginViewComponent },
{ path: 'home', component: HomeViewComponent },
{
path: 'reload',
children: [{
path: '**',
component: ReloadComponent
}]
},
{ path: '**', redirectTo: 'login'}
])
],
exports: [
RouterModule,
],
providers: [],
})
export class AppRoutingModule {}
Pour l'utiliser, il suffit d'ajouter reload à l'URL où nous voulons aller:
this.router.navigateByUrl('reload/some/route/again/fresh', {skipLocationChange: true})
Un peu hardcore mais
this.router.onSameUrlNavigation = 'reload';
this.router.navigateByUrl(this.router.url).then(() => {
this.router.onSameUrlNavigation = 'ignore';
});
Une solution consiste à passer un paramètre factice (c'est-à-dire le temps en secondes), de cette façon le lien est toujours rechargé:
this.router.navigate(["/url", {myRealData: RealData, dummyData: (new Date).getTime()}])
Autant que je sache, cela ne peut pas être fait avec le routeur dans Angular 2. Mais vous pouvez simplement faire:
window.location.href = window.location.href
Recharger la vue.
Je crois que cela a été résolu (nativement) dans Angular 6+; vérifier
Mais cela fonctionne pour un itinéraire entier (inclut également tous les itinéraires pour enfants)
Pour cibler un seul composant, procédez comme suit: Utilisez un paramètre de requête qui change afin de pouvoir naviguer autant de fois que vous le souhaitez.
Au point de navigation (classe)
this.router.navigate(['/route'], {
queryParams: { 'refresh': Date.now() }
});
Dans le composant que vous souhaitez "actualiser/recharger"
// . . . Component Class Body
$_route$: Subscription;
constructor (private _route: ActivatedRoute) {}
ngOnInit() {
this.$_route$ = this._route.queryParams.subscribe(params => {
if (params['refresh']) {
// Do Something
// Could be calling this.ngOnInit() PS: I Strongly advise against this
}
});
}
ngOnDestroy() {
// Always unsubscribe to prevent memory leak and unexpected behavior
this.$_route$.unsubscribe();
}
// . . . End of Component Class Body
Très frustrant que Angular encore ne semble pas inclure une bonne solution pour cela. J'ai soulevé un problème de github ici: https://github.com/angular/angular/issues/3184
En attendant, voici ma solution de contournement. Il s’appuie sur certaines des solutions suggérées ci-dessus, mais je pense qu’elle est un peu plus robuste. Cela implique de placer le service de routeur dans un "ReloadRouter
", qui prend en charge la fonctionnalité de rechargement et ajoute également un RELOAD_PLACEHOLDER
à la configuration du routeur principal. Ceci est utilisé pour la navigation intermédiaire et évite de déclencher d'autres itinéraires (ou gardes).
Remarque: Utilisez uniquement le paramètre ReloadRouter
dans les cas où vous souhaitez la fonctionnalité de rechargement. Utilisez la normale Router
sinon.
import { Injectable } from '@angular/core';
import { NavigationExtras, Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class ReloadRouter {
constructor(public readonly router: Router) {
router.config.unshift({ path: 'RELOAD_PLACEHOLDER' });
}
public navigate(commands: any[], extras?: NavigationExtras): Promise<boolean> {
return this.router
.navigateByUrl('/RELOAD_PLACEHOLDER', {skipLocationChange: true})
.then(() => this.router.navigate(commands, extras));
}
}
Supposons que la route du composant que vous souhaitez actualiser soit view
, puis utilisez ceci:
this.router.routeReuseStrategy.shouldReuseRoute = function (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot) {
if (future.url.toString() === 'view' && curr.url.toString() === future.url.toString()) {
return false;
}
return (future.routeConfig === curr.routeConfig);
};
vous pouvez ajouter un debugger
à l'intérieur de la méthode pour savoir quel est l'itinéraire exact à suivre après avoir accédé à "departments/:id/employees"
.
s'abonner aux changements de paramètres de route
// parent param listener ie: "/:id"
this.route.params.subscribe(params => {
// do something on parent param change
let parent_id = params['id']; // set slug
});
// child param listener ie: "/:id/:id"
this.route.firstChild.params.subscribe(params => {
// do something on child param change
let child_id = params['id'];
});
Si vous changez de route via Router Link Suivez ceci:
constructor(public routerNavigate: Router){
this.router.routeReuseStrategy.shouldReuseRoute = function () {
return false;
};
this.router.events.subscribe((evt) => {
if (evt instanceof NavigationEnd) {
this.router.navigated = false;
}
})
}
Ce code ci-dessous fonctionnera:
logoFn(url: any) {
this.router.routeReuseStrategy.shouldReuseRoute = function () {
return false;
};
this.router.navigate(['']); or
this.router.navigate([url]);
}