Angular: Jak zaktualizować queryParams bez zmiany trasy

127

Próbuję zaktualizować (dodać, usunąć) queryParams ze składnika. W angularJS było to możliwe dzięki:

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

Mam aplikację z listą, którą użytkownik może filtrować, porządkować itp. I chciałbym ustawić w queryParams adresu URL wszystkie filtry aktywowane, aby mógł skopiować / wkleić adres URL lub udostępnić go komuś innemu.

Nie chcę jednak, aby moja strona była ładowana ponownie po każdym wybraniu filtru.

Czy da się to zrobić z nowym routerem?

Olivier
źródło

Odpowiedzi:

273

Możesz przejść do aktualnej trasy z nowymi parametrami zapytania, które nie przeładują strony, ale zaktualizują parametry zapytania.

Coś takiego (w komponencie):

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

Zwróć uwagę, że chociaż nie ładuje ponownie strony, wypchnie nowy wpis do historii przeglądarki. Jeśli chcesz zamienić go w historii zamiast dodawać tam nową wartość, możesz użyć { queryParams: queryParams, replaceUrl: true }.

EDYCJA: Jak już wskazano w komentarzach, w moim oryginalnym przykładzie brakowało []tej relativeTowłaściwości, więc mogła również zmienić trasę, a nie tylko parametry zapytania. Prawidłowe this.router.navigateużycie będzie w tym przypadku:

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

Ustawienie nowej wartości parametru na nullspowoduje usunięcie parametru z adresu URL.

Radosław Roszkowiak
źródło
30
Musiałem użyć []zamiast, ['.']aby to zadziałało
Jaime Gómez
5
Należy użyć queryParams ['relativeTo'] = this.activatedRoute; aby nawigacja
odnosiła
3
Dobre rozwiązanie do rozwiązania problemu PO. To, czego ci to nie daje, chyba że czegoś mi brakuje, to możliwość przechodzenia wstecz i do przodu w historii bieżącej strony (np. Zmiana filtra lub kolejności 5 razy, każdy ma własny adres URL, ale ten sam komponent) i ma zawartość strony wygląda tak, jakbyś uzyskał bezpośredni dostęp do tych 5 adresów URL. Myślę, że możesz to zrobić ręcznie za pomocą this.activatedRoute.queryParams.subscribei wykonać różne aktualizacje w swoim komponencie, ale czy istnieje prosty sposób Angular, aby po prostu załadować trasę tak, aby wstecz i do przodu działały automatycznie?
jmq
1
kiedy używasz router.navigate, przewiniesz górę okna, jakieś pomysły jak to wyłączyć?
Hese
1
@Hese, na pewno? Nie sądzę, żeby przewinął się do góry. Spójrz na ten przykład: stackblitz.com/edit/angular-sdtsew?file=src/app/…
Radosław Roszkowiak
23

Odpowiedź @ Radosława Roszkowiaka jest prawie poprawna, ale relativeTo: this.routejest to wymagane, jak poniżej:

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

changeQuery() {
  this.router.navigate(['.'], { relativeTo: this.route, queryParams: { ... }});
}
Robert
źródło
14

W Angular 5 możesz łatwo uzyskać i zmodyfikować kopię urlTree , analizując bieżący adres URL. Obejmuje to parametry i fragmenty zapytań.

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

  this.router.navigateByUrl(urlTree); 

„Prawidłowym sposobem” modyfikacji parametru zapytania jest prawdopodobnie użycie createUrlTree, jak poniżej, które tworzy nowe UrlTree z bieżącego, jednocześnie pozwalając nam modyfikować go za pomocą 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); 
}

Aby w ten sposób usunąć parametr zapytania, możesz ustawić go na undefinedlub null.

bjornalm
źródło
2
navigateByUrlróżni się navigate- nie tylko z parametrem UrlTree. Zobacz stackoverflow.com/a/45025432/271012
Drenai
9

Próbować

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

będzie działać dla nawigacji po tej samej trasie, z wyjątkiem pojedynczych cudzysłowów.

Prudhvi Raj
źródło
Szukałem dokładnie tego. Dziękuję Ci!!!
cevaris
7

Odpowiedź z większością głosów częściowo mi pomogła. Adres URL przeglądarki pozostał taki sam, ale mój routerLinkActivenie działał po nawigacji.

Moim rozwiązaniem było użycie 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());
  }
}

Użyłem HttpParams do zbudowania ciągu zapytania, ponieważ używałem go już do wysyłania informacji za pomocą httpClient. ale możesz po prostu zbudować go samodzielnie.

a this._router.url.split("?")[0], służy do usunięcia całego poprzedniego ciągu zapytania z bieżącego adresu URL.

moi_meme
źródło
4
To POWINNO być akceptowaną odpowiedzią, router.navigates odświeża również ngOnit, location.go NIE robi tego! Jest to naprawdę ważne, ponieważ jeśli twój komponent wykonuje jakąś logikę ngOnit (wywołania HTTP itp.), Zostanie wywołany ponownie, gdy użyjesz router.navigate. Nie chcesz tego.
Danny Hoeve
Dlaczego potrzebujesz routera tylko dla adresu URL? Czy nie jest this.location.path().split...lepiej?
Vladimir
@Vladimir możesz mieć rację, użyłem go w innym celu w moim komponencie, więc nie tylko do tego. Nie mam jednak czasu na weryfikację.
moi_meme
To nie zadziała, jeśli chcesz zachować parametry zapytania, na przykład parametry promocji lub śledzenia Google
Jon Tinsman
5

Skończyło się na połączeniu urlTreezlocation.go

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

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

Nie jestem pewien, czy toStringmoże powodować problemy, ale niestety location.gowydaje się, że jest oparty na ciągach.

Razze
źródło
4

Jeśli chcesz zmienić parametry zapytania bez zmiany trasy. zobacz poniższy przykład może ci pomóc: aktualna trasa to: / search & Docelowa trasa to (bez strony przeładowania): / search? query = love

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

uwaga: możesz użyć this.router.navigate (['szukaj'] zamiast this.router.navigate (['.']

Azeem Chauhan
źródło
Nie jestem pewien, czy [.] Jest lepszym podejściem niż relativeTo:, ale .then()był pomocny - nie był świadomy, że funkcja navigate () zwróciła obietnicę, więc cieszę się, że opublikowałeś!
Drenai
0

Najpierw musimy zaimportować moduł routera z routera kątowego i zadeklarować jego alias

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

1. Możesz zmienić parametry zapytania za pomocą funkcji „router.navigate” i przekazać parametry zapytania

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

Zaktualizuje parametry zapytania w bieżącej, tj. Aktywowanej trasie

  1. Poniższe przekieruje do strony abc z _id, dniem i nazwą jako parametrami zapytania

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

    Zaktualizuje parametry zapytania w trasie „abc” wraz z trzema parametrami zapytania

Aby pobrać parametry zapytania: -

    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
źródło