Angular: Cara memperbarui queryParams tanpa mengubah rute

126

Saya mencoba memperbarui (menambah, menghapus) queryParams dari sebuah komponen. Di angularJS, itu dulunya mungkin berkat:

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

Saya memiliki aplikasi dengan daftar yang dapat difilter, dipesan, dll. Dan saya ingin menyetel di queryParams dari url semua filter yang diaktifkan sehingga dia dapat menyalin / menempel url atau membagikannya dengan orang lain.

Namun, saya tidak ingin halaman saya dimuat ulang setiap kali filter dipilih.

Apakah ini bisa dilakukan dengan router baru?

Olivier
sumber

Jawaban:

272

Anda dapat menavigasi ke rute saat ini dengan parameter kueri baru, yang tidak akan memuat ulang halaman Anda, tetapi akan memperbarui parameter kueri.

Sesuatu seperti (dalam komponen):

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

Perhatikan, meskipun tidak memuat ulang halaman, ini akan mendorong entri baru ke riwayat browser. Jika Anda ingin menggantinya dalam sejarah daripada menambahkan nilai baru di sana, Anda bisa menggunakan { queryParams: queryParams, replaceUrl: true }.

EDIT: Seperti yang sudah ditunjukkan di komentar, []dan relativeToproperti hilang dalam contoh asli saya, jadi itu bisa mengubah rute juga, bukan hanya parameter kueri. Penggunaan yang tepat this.router.navigatedalam hal ini:

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

Mengatur nilai parameter baru menjadi nullakan menghapus parameter dari URL.

Radosław Roszkowiak
sumber
30
Saya harus menggunakan []alih-alih ['.']membuatnya berfungsi
Jaime Gómez
5
Perlu menggunakan queryParams ['relativeTo'] = this.activatedRoute; untuk membuat navigasi relatif ke halaman saat ini
klonq
3
Solusi bagus untuk memecahkan masalah OP. Apa yang tidak membuat Anda, kecuali saya melewatkan sesuatu, adalah kemampuan untuk mundur dan maju dalam riwayat halaman Anda saat ini (misalnya mengubah filter atau memesan 5 kali, masing-masing memiliki URL sendiri tetapi komponen yang sama) dan memiliki konten halaman muncul bagaimana jika Anda mengakses 5 URL tersebut secara langsung. Saya pikir Anda dapat melakukannya secara manual melalui this.activatedRoute.queryParams.subscribedan melakukan berbagai pembaruan dalam komponen Anda, tetapi apakah ada cara Angular sederhana untuk memuat rute sedemikian rupa sehingga maju dan mundur akan bekerja secara otomatis?
jmq
1
saat menggunakan router.navigate itu akan menggulir bagian atas jendela, ada ide bagaimana menonaktifkan ini?
Dia
1
@Hese, apakah kamu yakin? Saya tidak berpikir itu akan bergulir ke atas. Silakan lihat contoh ini: stackblitz.com/edit/angular-sdtsew?file=src/app/…
Radosław Roszkowiak
23

Jawaban @ Radosław Roszkowiak hampir benar kecuali relativeTo: this.routediperlukan seperti di bawah ini:

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

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

Di Angular 5 Anda dapat dengan mudah mendapatkan dan memodifikasi salinan urlTree dengan mengurai url saat ini. Ini akan menyertakan parameter dan fragmen kueri.

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

  this.router.navigateByUrl(urlTree); 

"Cara yang benar" untuk mengubah parameter kueri mungkin dengan createUrlTree seperti di bawah ini yang membuat UrlTree baru dari saat ini sambil membiarkan kami memodifikasinya menggunakan 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); 
}

Untuk menghapus parameter kueri dengan cara ini Anda dapat mengaturnya ke undefinedatau null.

bjornalm.dll
sumber
2
navigateByUrlberbeda dengan navigate- tidak hanya dengan parameter UrlTree. Lihat stackoverflow.com/a/45025432/271012
Drenai
9

Mencoba

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

akan berfungsi untuk navigasi rute yang sama selain tanda kutip tunggal.

Prudhvi Raj
sumber
Saya mencari hal yang tepat ini. Terima kasih!!!
cevaris
7

Jawaban dengan suara terbanyak sebagian berhasil untuk saya. Url browser tetap sama tetapi url saya routerLinkActivetidak lagi berfungsi setelah navigasi.

Solusi saya adalah menggunakan 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());
  }
}

Saya menggunakan HttpParams untuk membangun string kueri karena saya sudah menggunakannya untuk mengirim informasi dengan httpClient. tapi Anda bisa membuatnya sendiri.

dan this._router.url.split("?")[0], adalah untuk menghapus semua string kueri sebelumnya dari url saat ini.

moi_meme
sumber
4
Ini HARUS menjadi jawaban yang diterima, router.navigates juga menyegarkan ngOnit, location.go TIDAK melakukan ini! Ini sangat penting karena jika komponen Anda melakukan beberapa logika ngOnit (panggilan HTTP, dll.), Mereka akan dipanggil lagi saat Anda menggunakan router.navigate. Anda tidak menginginkan ini.
Danny Hoeve
Mengapa Anda membutuhkan router, hanya untuk url? Bukankah this.location.path().split...lebih baik?
Vladimir
@Vladimir Anda mungkin benar, saya menggunakannya untuk tujuan lain di komponen saya, jadi bukan hanya untuk itu. Saya tidak punya waktu untuk memvalidasi.
moi_meme
Ini tidak akan berfungsi jika Anda ingin mempertahankan parameter kueri, misalnya parameter promosi atau pelacakan google
Jon Tinsman
5

Saya akhirnya menggabungkan urlTreedenganlocation.go

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

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

Tidak yakin apakah toStringdapat menyebabkan masalah, tetapi sayangnya location.go, tampaknya berbasis string.

Razze
sumber
4

Jika Anda ingin mengubah parameter kueri tanpa mengubah rute. lihat contoh di bawah ini dapat membantu Anda: rute saat ini adalah: / search & Target route adalah (tanpa halaman reload): / search? query = love

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

harap dicatat: Anda dapat menggunakan this.router.navigate (['search'] daripada this.router.navigate (['.']

Azeem Chauhan
sumber
Saya tidak yakin bahwa [.] Adalah pendekatan yang lebih baik daripada relativeTo:, tetapi .then()sangat membantu - tidak sadar bahwa navigation () mengembalikan janji, sangat senang Anda memposting!
Drenai
0

Pertama, kita perlu mengimpor modul router dari router sudut dan menyatakan nama aliasnya

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

1. Anda dapat mengubah parameter kueri dengan menggunakan fungsi "router.navigate" dan meneruskan parameter kueri

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

Ini akan memperbarui parameter kueri di rute yaitu diaktifkan saat ini

  1. Di bawah ini akan dialihkan ke halaman abc dengan _id, hari dan nama sebagai parameter kueri

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

    Ini akan memperbarui parameter kueri di rute "abc" bersama dengan tiga parameter kueri

Untuk mengambil parameter kueri: -

    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
sumber