Angular: So aktualisieren Sie queryParams, ohne die Route zu ändern

124

Ich versuche, queryParams von einer Komponente zu aktualisieren (hinzuzufügen, zu entfernen). In angleJS war dies früher möglich dank:

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

Ich habe eine App mit einer Liste, die der Benutzer filtern, bestellen usw. kann, und ich möchte in den Abfrageparametern der URL alle aktivierten Filter festlegen, damit er die URL kopieren / einfügen oder für andere Personen freigeben kann.

Allerdings mag ich nicht meine Seite neu geladen wird jedes Mal , wenn ein Filter ausgewählt.

Ist das mit dem neuen Router machbar?

Olivier
quelle

Antworten:

269

Sie können mit neuen Abfrageparametern zur aktuellen Route navigieren, wodurch Ihre Seite nicht neu geladen, sondern die Abfrageparameter aktualisiert werden.

So etwas wie (in der Komponente):

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

Beachten Sie, dass die Seite zwar nicht neu geladen wird, jedoch ein neuer Eintrag in den Browserverlauf verschoben wird. Wenn Sie es im Verlauf ersetzen möchten, anstatt dort einen neuen Wert hinzuzufügen, können Sie es verwenden { queryParams: queryParams, replaceUrl: true }.

BEARBEITEN: Wie bereits in den Kommentaren erwähnt, fehlte []die relativeToEigenschaft in meinem ursprünglichen Beispiel, sodass auch die Route geändert werden konnte, nicht nur die Abfrageparameter. Die ordnungsgemäße this.router.navigateVerwendung ist in diesem Fall:

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

Wenn Sie den neuen Parameterwert auf setzen, nullwird der Parameter aus der URL entfernt.

Radosław Roszkowiak
quelle
30
Ich musste verwenden, []anstatt es ['.']zum Laufen zu bringen
Jaime Gómez
5
Muss queryParams ['relativeTo'] = this.activatedRoute verwenden; um die Navigation relativ zur aktuellen Seite zu machen
klonq
3
Gute Lösung zur Lösung des OP-Problems. Was es Ihnen nicht bringt, es sei denn, ich vermisse etwas, ist die Möglichkeit, in Ihrem Verlauf der aktuellen Seite vorwärts und rückwärts zu gehen (z. B. Filter oder Bestellung fünfmal geändert, jede mit eigener URL, aber derselben Komponente) und die zu haben Der Inhalt der Seite wird so angezeigt, als würden Sie direkt auf diese 5 URLs zugreifen. Ich denke, Sie könnten dies manuell über this.activatedRoute.queryParams.subscribeIhre Komponente durchführen und verschiedene Aktualisierungen in Ihrer Komponente vornehmen. Gibt es jedoch eine einfache Angular-Methode, um die Route so zu laden, dass das Vor- und Zurückschalten automatisch funktioniert?
jmq
1
Wenn Sie router.navigate verwenden, wird oben im Fenster gescrollt. Gibt es Ideen, wie Sie dies deaktivieren können?
Hese
1
@Hese, bist du sicher? Ich glaube nicht, dass es nach oben scrollen wird. Bitte schauen Sie sich dieses Beispiel an: stackblitz.com/edit/angular-sdtsew?file=src/app/…
Radosław Roszkowiak
22

@ Radosław Roszkowiaks Antwort ist fast richtig, außer dass relativeTo: this.routedies wie folgt erforderlich ist:

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

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

In Angular 5 können Sie einfach eine Kopie des urlTree abrufen und ändern, indem Sie die aktuelle URL analysieren . Dies umfasst Abfrageparameter und Fragmente.

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

  this.router.navigateByUrl(urlTree); 

Der „richtige Weg“ einen Abfrageparameter zu ändern , ist wahrscheinlich mit dem createUrlTree wie , unter dem ein neues UrlTree aus dem Strom erzeugt , während wir es mit Stich gelassen ändern 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); 
}

Um einen Abfrageparameter auf diese Weise zu entfernen, können Sie ihn auf undefinedoder setzen null.

bjornalm
quelle
2
navigateByUrlunterscheidet sich von navigate- nicht nur mit dem UrlTree-Parameter. Siehe stackoverflow.com/a/45025432/271012
Drenai
9

Versuchen

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

funktioniert für dieselbe Routennavigation außer in einfachen Anführungszeichen.

Prudhvi Raj
quelle
Ich habe genau das gesucht. Danke dir!!!
Cevaris
7

Die Antwort mit den meisten Stimmen hat teilweise für mich funktioniert. Die Browser-URL blieb gleich, aber meinerouterLinkActive funktionierte nach der Navigation nicht mehr.

Meine Lösung war die Verwendung von 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());
  }
}

Ich habe HttpParams verwendet, um die Abfragezeichenfolge zu erstellen, da ich sie bereits zum Senden von Informationen mit httpClient verwendet habe. aber du kannst es einfach selbst bauen.

und das this._router.url.split("?")[0]ist, alle vorherigen Abfragezeichenfolgen aus der aktuellen URL zu entfernen.

moi_meme
quelle
4
Dies sollte die akzeptierte Antwort sein, die router.navigates aktualisiert auch die ngOnit, location.go tut dies NICHT! Dies ist sehr wichtig, da Ihre Komponente, wenn sie eine ngOnit-Logik (HTTP-Aufrufe usw.) ausführt, bei Verwendung von router.navigate erneut aufgerufen wird. Das willst du nicht.
Danny Hoeve
Warum brauchen Sie einen Router nur für die URL? Ist nicht this.location.path().split...besser
Vladimir
@Vladimir Sie haben vielleicht Recht, ich habe es für andere Zwecke in meiner Komponente verwendet, also nicht nur dafür. Ich habe jedoch keine Zeit zur Validierung.
moi_meme
Dies funktioniert nicht, wenn Sie Abfrageparameter beibehalten möchten, z. B. Promotion- oder Google Tracking-Parameter
Jon Tinsman,
5

Ich landete Kombination urlTreemitlocation.go

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

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

Ich bin mir nicht sicher, ob toStringdies Probleme verursachen kann location.go, scheint aber leider stringbasiert zu sein.

Razze
quelle
4

Wenn Sie Abfrageparameter ändern möchten, ohne die Route zu ändern. Das folgende Beispiel könnte Ihnen helfen: Die aktuelle Route lautet: / search & Die Zielroute lautet (ohne Seite zum erneuten Laden): / search? query = love

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

Bitte beachten Sie: Sie können this.router.navigate (['search'] anstelle von this.router.navigate (['.']) verwenden.

Azeem Chauhan
quelle
Ich bin mir nicht sicher, ob das [.] Ein besserer Ansatz ist als relativeTo:, aber das .then()war hilfreich - war sich nicht bewusst, dass navigieren () ein Versprechen zurückgegeben hat, also froh, dass Sie gepostet haben!
Drenai
0

Zuerst müssen wir das Routermodul vom Winkelrouter importieren und seinen Aliasnamen deklarieren

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

1. Sie können die Abfrageparameter mithilfe der Funktion "router.navigate" ändern und die Abfrageparameter übergeben

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

Die Abfrageparameter werden in der aktuell dh aktivierten Route aktualisiert

  1. Im Folgenden wird auf die abc-Seite mit _id, Tag und Name als Abfrageparameter umgeleitet

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

    Die Abfrageparameter in der "abc" -Route werden zusammen mit drei Abfrageparametern aktualisiert

Zum Abrufen von Abfrageparametern: -

    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
quelle