web-dev-qa-db-fra.com

Comment recharger l'itinéraire actuel avec le routeur angular 2

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?

90
Pascal

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.

35
Yakov Fain

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

71
Arg0n

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

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

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é.

70
Simon McClive

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.

51
theo sharkson

Petit problème: utilisez le même chemin avec des paramètres factices. Par exemple-

refresh(){
  this.router.navigate(["/same/route/path?refresh=1"]);
}
28
newari

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]);
    });
  }
15
indreed

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) {

}
6
karthi

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 :)

5
Carli Beeli

Cela fonctionne pour moi comme un charme

this.router.navigateByUrl('/', {skipLocationChange: true}).then(()=>
this.router.navigate([<route>]));
4
Nitin Kamate

Pour moi, le codage en dur avec

this.router.routeReuseStrategy.shouldReuseRoute = function() {
    return false;
    // or
    return true;
};
3
V. Kalyuzhnyu

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.

  • Vous pouvez ensuite les gérer en vous abonnant à un itinéraire.
  • Vous pouvez l'utiliser avec la combinaison de runGuardsAndResolvers pour réexécuter les résolveurs

Laissez le routeur intact

  • Passez une actualisation à queryParam avec l'horodatage actuel dans l'URL et abonnez-vous à queryParams dans votre composant routé.
  • Utilisez l'événement activate du routeur-prise pour mettre la main sur le composant routé.

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.

2
Trafalgar

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)
2
ajay hariyal

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 () {

  }
2
Evandro Mendes

Dans mon cas:

const navigationExtras: NavigationExtras = {
    queryParams: { 'param': val }
};

this.router.navigate([], navigationExtras);

fonctionne correctement

2
Anton Zimm

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})
2
sabithpocker

Un peu hardcore mais

this.router.onSameUrlNavigation = 'reload';
this.router.navigateByUrl(this.router.url).then(() => {

    this.router.onSameUrlNavigation = 'ignore';

});
2

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()}])
1
losciur

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.

1
HelloWorld

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
1
mbao01

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));
  }
}
0
Dan King

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".

0
Ebraheem Alrabee'

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'];
    });
0
Omar

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;
             }
          })
      }
0
Omkar Joshi

Ce code ci-dessous fonctionnera:

logoFn(url: any) {

    this.router.routeReuseStrategy.shouldReuseRoute = function () {
        return false;
    };
    this.router.navigate(['']); or
    this.router.navigate([url]);

}
0
Martin Jesu