Angular: come aggiornare queryParams senza modificare il percorso


126

Sto cercando di aggiornare (aggiungere, rimuovere) queryParams da un componente. In angularJS, era possibile grazie a:

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

Ho un'app con una lista che l'utente può filtrare, ordinare, ecc e vorrei impostare nella queryParams dell'url tutti i filtri attivati ​​in modo che possa copiare / incollare l'url o condividerlo con qualcun altro.

Tuttavia, non voglio che la mia pagina venga ricaricata ogni volta che viene selezionato un filtro.

È fattibile con il nuovo router?

Risposte:


272

Puoi navigare verso il percorso corrente con nuovi parametri di query, che non ricaricheranno la tua pagina, ma aggiorneranno i parametri di query.

Qualcosa come (nel componente):

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
    });
}

Nota che, sebbene non ricarichi la pagina, inserirà una nuova voce nella cronologia del browser. Se vuoi sostituirlo nella cronologia invece di aggiungere nuovo valore lì, puoi usare { queryParams: queryParams, replaceUrl: true }.

EDIT: come già sottolineato nei commenti, []e la relativeToproprietà mancava nel mio esempio originale, quindi avrebbe potuto cambiare anche il percorso, non solo i parametri di query. L' this.router.navigateutilizzo corretto sarà in questo caso:

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

L'impostazione del nuovo valore del parametro su nullrimuoverà il parametro dall'URL.


30
Ho dovuto usare []invece di ['.']farlo funzionare
Jaime Gómez

5
È necessario utilizzare queryParams ['relativeTo'] = this.activatedRoute; per effettuare la navigazione relativa alla pagina corrente
klonq

3
Bella soluzione per risolvere il problema dell'OP. Quello che non ti ottiene, a meno che non mi manchi qualcosa, è la possibilità di andare avanti e indietro nella cronologia della pagina corrente (ad esempio, filtro o ordine cambiato 5 volte, ciascuno con il proprio URL ma lo stesso componente) e avere il il contenuto della pagina apparirà come sarebbe se accedessi direttamente a quei 5 URL. Penso che potresti farlo manualmente tramite this.activatedRoute.queryParams.subscribee fare vari aggiornamenti nel tuo componente, ma esiste un semplice modo angolare per caricare il percorso in modo tale che avanti e indietro funzionino automaticamente?
jmq

1
quando si utilizza router.navigate scorrerà la parte superiore della finestra, qualche idea su come disabilitarlo?
Hese

1
@Hese, sei sicuro? Non credo che scorrerà fino all'inizio. Dai
Radosław Roszkowiak

23

La risposta di @ Radosław Roszkowiak è quasi corretta tranne che relativeTo: this.routeè richiesta come di seguito:

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

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

14

In Angular 5 puoi facilmente ottenere e modificare una copia di urlTree analizzando l'URL corrente. Ciò includerà parametri e frammenti di query.

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

  this.router.navigateByUrl(urlTree); 

Il "modo corretto" per modificare un parametro di query è probabilmente con createUrlTree come sotto, che crea un nuovo UrlTree dalla corrente mentre ci permette di modificarlo usando 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); 
}

Per rimuovere un parametro di query in questo modo è possibile impostarlo su undefinedo null.


2
navigateByUrlè diverso da navigate- non solo con il parametro UrlTree. Vedi stackoverflow.com/a/45025432/271012
Drenai

9

Provare

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

funzionerà per la stessa rotta di navigazione diversa dalle virgolette singole.


Stavo cercando questa cosa esatta. Grazie!!!
cevaris

7

La risposta con la maggior parte dei voti ha funzionato parzialmente per me. L'URL del browser è rimasto lo stesso ma il mio routerLinkActivenon funzionava più dopo la navigazione.

La mia soluzione era usare 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());
  }
}

Ho usato HttpParams per creare la stringa di query poiché la stavo già usando per inviare informazioni con httpClient. ma puoi costruirlo da solo.

e il this._router.url.split("?")[0], è quello di rimuovere tutta la stringa di query precedente dall'URL corrente.


4
Questa DOVREBBE essere la risposta accettata, router.navigates aggiorna anche ngOnit, location.go NON lo fa! Questo è molto importante perché se il tuo componente esegue un po 'di logica ngOnit (chiamate HTTP, ecc.) Verrà chiamato di nuovo quando usi router.navigate. Non lo vuoi.
Danny Hoeve

Perché hai bisogno del router, solo per l'URL? Non è this.location.path().split...meglio?
Vladimir

@Vladimir potresti avere ragione, lo stavo usando per altri scopi nel mio componente, quindi non era solo per quello. Non ho tempo per convalidare però.
moi_meme

Questo non funzionerà se desideri preservare i parametri della query, ad esempio la promozione oi parametri di monitoraggio di Google
Jon Tinsman

5

Ho finito per combinarmi urlTreeconlocation.go

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

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

Non sono sicuro che toStringpossa causare problemi, ma sfortunatamente location.gosembra essere basato su stringhe.


4

Se desideri modificare i parametri della query senza modificare il percorso. vedere l'esempio sotto potrebbe aiutarti: il percorso corrente è: / search & Il percorso di destinazione è (senza ricaricare la pagina): / search? query = love

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

nota: puoi usare this.router.navigate (['cerca'] invece di this.router.navigate (['.']


Non sono sicuro che [.] Sia un approccio migliore di relativeTo:, ma è .then()stato utile - non sapevo che navigate () avesse restituito una promessa, quindi sono contento che tu abbia pubblicato!
Drenai

0

Per prima cosa, dobbiamo importare il modulo router dal router angolare e dichiarare il suo nome alias

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

1. È possibile modificare i parametri della query utilizzando la funzione "router.navigate" e passare i parametri della query

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

Aggiornerà i parametri della query nell'itinerario attualmente attivato

  1. Quanto segue reindirizzerà alla pagina abc con _id, giorno e nome come parametri della query

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

    Aggiornerà i parametri della query nella route "abc" insieme a tre parametri della query

Per recuperare i parametri della query: -

    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
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.