Angular: Comment mettre à jour queryParams sans changer d'itinéraire

126

J'essaye de mettre à jour (ajouter, supprimer) queryParams d'un composant. Dans angularJS, c'était possible grâce à:

$location.search('f', 'filters[]'); // setter
$location.search()['filters[]'];    // getter

J'ai une application avec une liste que l'utilisateur peut filtrer, commander, etc. et je voudrais définir dans le queryParams de l'url tous les filtres activés afin qu'il puisse copier / coller l'url ou la partager avec quelqu'un d'autre.

Cependant, je ne souhaite pas que ma page soit rechargée à chaque fois qu'un filtre est sélectionné.

Est-ce faisable avec le nouveau routeur?

Olivier
la source

Réponses:

272

Vous pouvez accéder à l'itinéraire actuel avec de nouveaux paramètres de requête, qui ne rechargeront pas votre page, mais mettront à jour les paramètres de requête.

Quelque chose comme (dans le composant):

constructor(private router: Router) { }

public myMethodChangingQueryParams() {
  const queryParams: Params = { myParam: 'myNewValue' };

  this.router.navigate(
    [], 
    {
      relativeTo: activatedRoute,
      queryParams: queryParams, 
      queryParamsHandling: 'merge', // remove to replace all query params by provided
    });
}

Notez que même s'il ne rechargera pas la page, il poussera une nouvelle entrée dans l'historique du navigateur. Si vous souhaitez le remplacer dans l'historique au lieu d'y ajouter une nouvelle valeur, vous pouvez utiliser { queryParams: queryParams, replaceUrl: true }.

EDIT: Comme déjà souligné dans les commentaires, []et la relativeTopropriété manquait dans mon exemple d'origine, donc cela aurait pu également changer l'itinéraire, pas seulement les paramètres de requête. La bonne this.router.navigateutilisation sera dans ce cas:

this.router.navigate(
  [], 
  {
    relativeTo: this.activatedRoute,
    queryParams: { myParam: 'myNewValue' },
    queryParamsHandling: 'merge'
  });

Définir la nouvelle valeur de paramètre sur nullsupprimera le paramètre de l'URL.

Radosław Roszkowiak
la source
30
Je devais utiliser []au lieu de ['.']pour que cela fonctionne
Jaime Gómez
5
Besoin d'utiliser queryParams ['relativeTo'] = this.activatedRoute; pour faire la navigation par rapport à la page courante
klonq
3
Belle solution pour résoudre le problème de l'OP. Ce que cela ne vous permet pas, à moins que je ne manque quelque chose, c'est la possibilité de revenir en arrière dans votre historique de la page actuelle (par exemple, changement de filtre ou d'ordre 5 fois, chacun ayant sa propre URL mais le même composant) et avoir le le contenu de la page apparaît comme il le ferait si vous accédiez directement à ces 5 URL. Je pense que vous pouvez accomplir cela manuellement via this.activatedRoute.queryParams.subscribeet effectuer diverses mises à jour dans votre composant, mais existe-t-il un moyen angulaire simple de charger simplement la route de sorte que le va-et-vient fonctionne automatiquement?
jmq
1
lors de l'utilisation de router.navigate, il fera défiler le haut de la fenêtre, des idées comment désactiver cela?
Hese
1
@Hese, tu es sûr? Je ne pense pas qu'il défilera vers le haut. Veuillez jeter un œil à cet exemple: stackblitz.com/edit/angular-sdtsew?file=src/app/…
Radosław Roszkowiak
23

La réponse de @ Radosław Roszkowiak est presque correcte, sauf que cela relativeTo: this.routeest requis comme ci-dessous:

constructor(
  private router: Router,
  private route: ActivatedRoute,
) {}

changeQuery() {
  this.router.navigate(['.'], { relativeTo: this.route, queryParams: { ... }});
}
Robert
la source
14

Dans Angular 5, vous pouvez facilement obtenir et modifier une copie de l' urlTree en analysant l'url actuelle. Cela inclura les paramètres de requête et les fragments.

  let urlTree = this.router.parseUrl(this.router.url);
  urlTree.queryParams['newParamKey'] = 'newValue';

  this.router.navigateByUrl(urlTree); 

La "bonne façon" de modifier un paramètre de requête est probablement avec le createUrlTree comme ci-dessous qui crée un nouvel UrlTree à partir du courant tout en nous permettant de le modifier à l'aide de NavigationExtras .

import { Router } from '@angular/router';

constructor(private router: Router) { }

appendAQueryParam() {

  const urlTree = this.router.createUrlTree([], {
    queryParams: { newParamKey: 'newValue' },
    queryParamsHandling: "merge",
    preserveFragment: true });

  this.router.navigateByUrl(urlTree); 
}

Pour supprimer un paramètre de requête de cette manière, vous pouvez le définir sur undefinedou null.

Bjornalm
la source
2
navigateByUrlest différent de navigate- pas seulement avec le paramètre UrlTree. Voir stackoverflow.com/a/45025432/271012
Drenai
9

Essayer

this.router.navigate([], { 
  queryParams: {
    query: value
  }
});

fonctionnera pour la même navigation d'itinéraire autre que les guillemets simples.

Prudhvi Raj
la source
Je cherchais cette chose exacte. Je vous remercie!!!
cevaris le
7

La réponse avec le plus de votes a partiellement fonctionné pour moi. L'URL du navigateur est restée la même mais mon routerLinkActivene fonctionnait plus après la navigation.

Ma solution était d'utiliser lotation.go:

import { Component } from "@angular/core";
import { Location } from "@angular/common";
import { HttpParams } from "@angular/common/http";

export class whateverComponent {
  constructor(private readonly location: Location, private readonly router: Router) {}

  addQueryString() {
    const params = new HttpParams();
    params.append("param1", "value1");
    params.append("param2", "value2");
    this.location.go(this.router.url.split("?")[0], params.toString());
  }
}

J'ai utilisé HttpParams pour créer la chaîne de requête car je l'utilisais déjà pour envoyer des informations avec httpClient. mais vous pouvez simplement le construire vous-même.

et le this._router.url.split("?")[0], est de supprimer toute la chaîne de requête précédente de l'url actuelle.

moi_meme
la source
4
Cela DEVRAIT être la réponse acceptée, le router.navigates actualise également le ngOnit, location.go ne le fait PAS! Ceci est vraiment important car si votre composant exécute une logique ngOnit (appels HTTP, etc.), il sera à nouveau appelé lorsque vous utilisez router.navigate. Tu ne veux pas de ça.
Danny Hoeve
Pourquoi avez-vous besoin d'un routeur, uniquement pour l'URL? N'est-ce pas this.location.path().split...mieux?
Vladimir
@Vladimir vous avez peut-être raison, je l'utilisais à d'autres fins dans mon composant, donc ce n'était pas seulement pour ça. Je n'ai cependant pas le temps de valider.
moi_meme
Cela ne fonctionnera pas si vous souhaitez conserver les paramètres de requête, par exemple les paramètres de promotion ou de suivi Google
Jon Tinsman
5

J'ai fini par combiner urlTreeaveclocation.go

const urlTree = this.router.createUrlTree([], {
       relativeTo: this.route,
       queryParams: {
           newParam: myNewParam,
       },
       queryParamsHandling: 'merge',
    });

    this.location.go(urlTree.toString());

Je ne sais pas si cela toStringpeut causer des problèmes, mais malheureusement location.go, cela semble être basé sur une chaîne.

Razze
la source
4

Si vous souhaitez modifier les paramètres de requête sans modifier l'itinéraire. voir ci-dessous l'exemple pourrait vous aider: la route actuelle est: / search & La route cible est (sans la page de rechargement): / search? query = love

submit(value: string) {
{ this.router.navigate( ['.'],  { queryParams: { query: value } })
    .then(_ => this.search(q));
}
search(keyword:any) { 
//do some activity using }

Veuillez noter: vous pouvez utiliser this.router.navigate (['search'] au lieu de this.router.navigate (['.']

Azeem Chauhan
la source
Je ne suis pas sûr que le [.] Soit une meilleure approche que relativeTo:, mais cela a .then()été utile - je ne savais pas que naviguer () a renvoyé une promesse, je suis ravi que vous ayez posté!
Drenai
0

Tout d'abord, nous devons importer le module de routeur du routeur angulaire et déclarer son nom d'alias

import { Router } from '@angular/router'; ---> import
class AbcComponent implements OnInit(){
constructor(
    private router: Router ---> decalre alias name
  ) { }
}

1. Vous pouvez modifier les paramètres de requête en utilisant la fonction "router.navigate" et transmettre les paramètres de requête

this.router.navigate([], { queryParams: {_id: "abc", day: "1", name: "dfd"} 
});

Il mettra à jour les paramètres de requête dans l'itinéraire actuel, c'est-à-dire activé

  1. Le ci-dessous redirigera vers la page abc avec _id, jour et nom comme paramètres de requête

    this.router.navigate (['/ abc'], {queryParams: {_id: "abc", jour: "1", nom: "dfd"}});

    Il mettra à jour les paramètres de requête dans l'itinéraire "abc" avec trois paramètres de requête

Pour récupérer les paramètres de requête: -

    import { ActivatedRoute } from '@angular/router'; //import activated routed

    export class ABC implements OnInit {

    constructor(
        private route: ActivatedRoute //declare its alias name
      ) {}

    ngOnInit(){
       console.log(this.route.snapshot.queryParamMap.get('_id')); //this will fetch the query params
    }
VIKAS KOHLI
la source