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.