web-dev-qa-db-fra.com

Recharger la route Angular 4+ avec le même paramètre d'URL

J'ai effectué des recherches sur le rechargement d'une route angulaire 4+ et il semble que la méthode préférée consiste à écouter les modifications des paramètres d'URL au sein du composant et à y réinitialiser le composant.

Le problème que je rencontre est de tenter de trouver une approche DRY (ne vous répétez pas) pour que cela fonctionne avec plusieurs composants, lorsque l'URL serait identique (y compris les paramètres). Dans AngularJS, cela était simple avec UI-router.

Cas d'utilisation:

J'ai un panneau de notification qui peut "flotter" au-dessus de n'importe quelle route. Lorsqu'une personne clique sur une notification, elle doit accéder au contenu auquel elle se rapporte - cela peut être de nombreux types de contenu différents.

Par exemple: /posts/:id ou /groups/:id ou /users/:id

Si l'utilisateur regarde déjà ce contenu, il ne recharge pas et ne s'actualise pas pour refléter le message de la notification. "John Doe a commenté votre message" (l'utilisateur peut consulter une version obsolète de ce message) ou "Jane Doe a accepté votre demande d'adhésion à un groupe" (l'utilisateur peut consulter la vue d'invité de ce groupe).

Je me suis penché sur l'utilisation de window.location.reload() pour détecter que la route est identique et que cela fonctionne, mais c'est hautement indésirable en raison de la surcharge qu'elle entraîne (réinitialisation angulaire, vérification de l'authentification, reconnexion de socket, etc.).

Toutes les suggestions seraient grandement appréciées!

9
Jamie Street

Vous devez souscrire des paramètres de route afin que, chaque fois que cela change, nous puissions gérer les changements. Vous trouverez ci-dessous un exemple de code de mon projet qui fonctionne parfaitement.

constructor(private router: Router) {
    this.route.params.subscribe(params => {
      this.initializePage(params['id']);
    });
}

initializePage(id:any){
//..Your code
// Consider this as your ngOnInIt() method and initialize everything here.
}

Ici, lorsque la valeur du paramètre change dans l’URL avec le même itinéraire, la page ne sera pas rechargée, mais simplement modifiée lorsque nous appelons initializePage (id) , ce qui réinitialisera tout.

J'espère que cela vous aidera. 

1
Vishw Patel

Dans ce cas, votre itinéraire ne change pas, seuls vos paramètres changent.

Pour résoudre ce problème, vous devez vous abonner aux paramètres ActivatedRoute.

export class MyClass implements OnInit {
   constructor(private activatedRoute: ActivatedRoute ) {
        this.activatedRoute.params.subscribe((params)=>{
          console.log('updatedParams', params);
        });
    }
}
0
Gregório Almeida

En this.router.url, vous obtiendrez l'URL de la page actuelle. Utilisez ensuite la navigation par routeur comme avec queryParames. Voici l'exemple de passage de queryParams en tant que page pour la pagination. Vous pouvez utiliser une approche similaire.

const url = this.router.url.split('?')[0]; // this will remove previous queryparms
    this.router.navigate([url], { queryParams: { page: $event } });

Il n'y a aucun moyen de simplement recharger la route lorsque rien n'a changé dans l'URL. En effet, les seules options que vous avez sont window.location.reload() et l'écoute des paramètres change. 

Pour la deuxième option, vous pouvez créer un service générique qui surveillera les modifications de l'argument id dans la chaîne de requête. Appelons-le IdWatchService et cela ressemblerait à ceci:

@Injectable()
export class IdWatchService {
  constructor(private route: ActivatedRoute) {
  }

  get idChange(): Observable<number | undefined> {
    return this.route.queryParams.map(p => p['id'] as number | undefined).distinctUntilChanged();
  }
}

Ensuite, vous pouvez ajouter ce service à la liste de providers sur les composants devant réagir aux modifications (PostsComponent, GroupsComponent, etc.). Et enfin, vous pouvez l’injecter dans ces mêmes composants et vous abonner à l’observable idChange:

@Component({
  templateUrl: './posts.component.html',
  providers: [
    IdWatchService
  ]
})
export class PostsComponent {
  constructor(idWatchService: IdWatchService) {
    idWatchService.idChange.subscribe(id => {
      // Load data for the new ID and refresh the view
    });
  }
}
0
Pavlo Glazkov

Je me suis retrouvé face au même scénario (cas d’utilisation très similaire) dans Angular 2. Comme d’autres réponses, j’ai trouvé qu’il n’existait aucune méthode intégrée permettant de le faire (l’hypothèse-cadre est peut-être que ce cas devrait être résolu simplement en écoutant changements dans les paramètres).

Comme vous, je ne voulais pas réécrire mon code. J'ai donc utilisé une solution différente, c'est un peu plus compliqué, mais cela a fonctionné sans grand besoin de changement.

La solution que j’ai utilisée consistait à créer une fausse route sous le même niveau de recherche que celui où vous devez recharger la page. Sur la route fictive, j’ai utilisé un DummyComponent qui reçoit dans la route des données décrivant la prochaine route à suivre (celle que nous souhaitons recharger) et à quels paramètres devrais-je lui transmettre (comme id mentionné ci-dessus), puis j’ai utilisé la classe Rounter injectée avec la méthode de navigation pour accéder à cet itinéraire. 

Je pense que cette solution sera beaucoup plus efficace que d’utiliser window.reload et qu’elle est assez simple à écrire. (Je ne peux pas copier cet exemple de code car je n'ai pas accès à ce code)

0
Ziv Glazer

Je faisais face au même problème avec la section de notification dans l'en-tête J'ai résolu ce problème avec DoCheck

import { Component, DoCheck } from '@angular/core';

In Class implémente l'interface DoCheck

export class HeaderComponent implements DoCheck {

Ensuite, utilisez la méthode ngDoCheck () et vérifiez si la valeur de la variable change, elle sera identique dans la zone de notification.

ngDoCheck() {
    // check if values changes
}
0
sankey