Ubah parameter rute tanpa memuat ulang di Angular 2

114

Saya membuat situs web real estat menggunakan Angular 2, Google Maps, dll. Dan ketika pengguna mengubah pusat peta, saya melakukan penelusuran ke API yang menunjukkan posisi peta saat ini serta radiusnya. Masalahnya, saya ingin mencerminkan nilai-nilai itu di url tanpa memuat ulang seluruh halaman. Apakah itu mungkin? Saya telah menemukan beberapa solusi menggunakan AngularJS 1.x tetapi tidak ada tentang Angular 2.

Marcos Basualdo
sumber
saya rasa jika Anda menggunakan [routerLink] = "['/ route', {param1: value1}] itu tidak akan memuat ulang halaman
Toolkit
tetapi bagaimana cara menambahkan parameter kueri lain?
Toolkit
2
☝️ itu akan menyebabkan halaman dimuat ulang
LifterCoder
Perlu diketahui bahwa jika Anda menggunakan SSR untuk membuat situs Anda kompatibel dengan SEO, ini adalah masalah yang bisa diperdebatkan.
Jonathan
@Jonathan, apakah itu? Karena Angular mengambil alih perutean setelah halaman statis ditampilkan, saya akan berpikir itu masih pertanyaan yang valid bahkan ketika menggunakan SSR.
adam0101

Jawaban:

92

Anda dapat menggunakan location.go(url)yang pada dasarnya akan mengubah url Anda, tanpa mengubah rute aplikasi.

CATATAN ini dapat menyebabkan efek lain seperti pengalihan ke rute anak dari rute saat ini.

Pertanyaan terkait yang menjelaskanlocation.gotidak akan intimRoutersampai terjadi perubahan.

Pankaj Parkar
sumber
2
Rute saya memiliki parameter bernama 'pencarian' di mana menerima versi serial dari bidang pencarian, ketika status daftar memuat untuk pertama kalinya saya hanya membaca parameter tersebut menggunakan this._routeParams.get ('search'), deserialize filter dan melakukan pencarian. Jika pengguna mengubah bidang pencarian, baik dengan menggunakan peta atau aspek pencarian, saya hanya membuat url yang benar menggunakan metode yang dihasilkan dari router var instruksi = this._router.generate (['Listing', {search: serializedFields}] ) dan kemudian menggunakan this._location.go (instruksi.urlPath) untuk mengubah url tanpa memuat ulang status.
Marcos Basualdo
20
Jika ada yang bertanya-tanya: impor {Location} dari 'angular2 / platform / common';
Kesarion
18
import { Location } from '@angular/common';dalam Angular 4
tehCivilian
2
Apakah Anda menyatakan konstruktor seperticonstructor(private location: Location){ }
Pankaj Parkar
2
@AdrianE Masalahnya kemungkinan besar Anda mengetik location.go()sementara Anda seharusnya mengetik this.location.go(). Saat Anda memancarkan this., Anda memanggil antarmuka lokasi Typecript.
georg-un
94

Pada RC6 Anda dapat melakukan hal berikut untuk mengubah URL tanpa mengubah status dan dengan demikian menyimpan riwayat rute Anda

    import {OnInit} from '@angular/core';

    import {Location} from '@angular/common'; 
    // If you dont import this angular will import the wrong "Location"

    @Component({
        selector: 'example-component',
        templateUrl: 'xxx.html'
    })
    export class ExampleComponent implements OnInit {
        
        constructor( private location: Location )
        {}

        ngOnInit() {    
            this.location.replaceState("/some/newstate/");
        }
    }
tjuzbumz.dll
sumber
Ini tidak berhasil untuk saya. Itu sitll mencoba memuat rute. Kesalahan konsol:Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'some/newstate'
Inigo
2
Gabungkan ini dengan pembuatan url seperti yang disarankan oleh @golfadas dan kami memiliki pemenangnya!
crowmagnumb
63

Menggunakan location.go(url)adalah cara yang harus dilakukan, tetapi alih-alih melakukan hardcode url, pertimbangkan untuk membuatnya menggunakan router.createUrlTree().

Mengingat bahwa Anda ingin melakukan panggilan router berikut: this.router.navigate([{param: 1}], {relativeTo: this.activatedRoute})tetapi tanpa memuat ulang komponen, itu dapat ditulis ulang sebagai:

const url = this.router.createUrlTree([], {relativeTo: this.activatedRoute, queryParams: {param: 1}}).toString()

 this.location.go(url);
golfadas
sumber
9
Jawaban ini memecahkan masalah saya. Satu pertanyaan, url yang dihasilkan di atas memiliki parameter yang dibatasi oleh ";" (titik koma). Apa yang harus kita lakukan untuk memisahkan setiap parameter dalam kueri dengan "&"?
Amarnath
2
ini adalah deklarasi createUrlTree (perintah: any [], navigationExtras ?: NavigationExtras). Anda harus menggunakan queryParams terletak navigationExtras not commads. createUrlTree ([], {relativeTo: this.activatedRoute, queryParams: {param: 1}})
kit
hanya untuk mengklarifikasi apa yang dikatakan @kit, lakukan ini:this.router.createUrlTree([], {relativeTo: this.activatedRoute, queryParams: {param: 1}}).toString()
bluegrounds
12

Bagi siapa pun seperti saya yang menemukan pertanyaan ini, berikut ini mungkin berguna.

Saya memiliki masalah serupa dan awalnya mencoba menggunakan location.go dan location.replaceState seperti yang disarankan dalam jawaban lain di sini. Namun saya mengalami masalah ketika saya harus menavigasi ke halaman lain di aplikasi karena navigasi relatif terhadap rute saat ini dan rute saat ini tidak diperbarui oleh location.go atau location.replaceState (router tidak tahu apa-apa tentang apa yang dilakukan ini pada URL)

Intinya saya membutuhkan solusi yang TIDAK memuat ulang halaman / komponen ketika parameter rute berubah tetapi DID memperbarui status rute secara internal.

Saya akhirnya menggunakan parameter kueri. Anda dapat menemukannya lebih lanjut di sini: https://angular-2-training-book.rangle.io/handout/routing/query_params.html

Jadi jika Anda perlu melakukan sesuatu seperti menyimpan pesanan dan mendapatkan ID pesanan, Anda dapat memperbarui URL halaman Anda seperti yang ditunjukkan di bawah ini. Memperbarui lokasi pusat dan data terkait pada peta akan serupa

// let's say we're saving an order. Initally the URL is just blah/orders
save(orderId) {
    // [Here we would call back-end to save the order in the database]

    this.router.navigate(['orders'], { queryParams: { id: orderId } });
    // now the URL is blah/orders?id:1234. We don't reload the orders
    // page or component so get desired behaviour of not seeing any 
    // flickers or resetting the page.
}

dan Anda terus melacaknya dalam metode ngOnInit seperti:

ngOnInit() {
    this.orderId = this.route
        .queryParamMap
        .map(params => params.get('id') || null);
    // orderID is up-to-date with what is saved in database now, or if
    // nothing is saved and hence no id query paramter the orderId variable
    // is simply null.
    // [You can load the order here from its ID if this suits your design]
}

Jika Anda perlu membuka halaman pesanan dengan pesanan baru (belum disimpan), Anda dapat melakukan:

this.router.navigate(['orders']);

Atau jika Anda perlu membuka halaman pesanan untuk pesanan yang sudah ada (tersimpan), Anda dapat melakukan:

this.router.navigate(['orders'], { queryParams: { id: '1234' } });
TornadoAli
sumber
10

Saya mengalami kesulitan besar untuk membuatnya bekerja dalam rilis RCx angular2. Paket Lokasi telah dipindahkan, dan menjalankan location.go () di dalam konstruktor () tidak akan berfungsi. Ini harus ngOnInit () atau yang lebih baru dalam siklus proses. Berikut beberapa contoh kode:

import {OnInit} from '@angular/core';
import {Location} from '@angular/common';

@Component({
  selector: 'example-component',
  templateUrl: 'xxx.html'
})
export class ExampleComponent implements OnInit
{
  constructor( private location: Location )
  {}

  ngOnInit()
  {    
    this.location.go( '/example;example_param=917' );
  }
}

Berikut adalah sumber daya sudut tentang masalah tersebut: https://angular.io/docs/ts/latest/api/common/index/Location-class.html https://angular.io/docs/ts/latest/api/ common / index / LocationStrategy-class.html

Luke Dupin
sumber
7

Saya menggunakan cara ini untuk mendapatkannya:

const queryParamsObj = {foo: 1, bar: 2, andThis: 'text'};

this.location.replaceState(
  this.router.createUrlTree(
    [this.locationStrategy.path().split('?')[0]], // Get uri
    {queryParams: queryParamsObj} // Pass all parameters inside queryParamsObj
  ).toString()
);

- EDIT -

Saya pikir saya harus menambahkan beberapa informasi lagi untuk ini.

Jika Anda menggunakan this.location.replaceState()router aplikasi Anda tidak diperbarui, jadi jika Anda menggunakan informasi router nanti tidak sama untuk ini di browser Anda. Misalnya jika Anda menggunakan localizeServiceuntuk mengubah bahasa, setelah mengganti bahasa aplikasi Anda kembali ke URL terakhir di mana Anda sebelumnya mengubahnya dengan this.location.replaceState().

Jika Anda tidak menginginkan perilaku ini, Anda dapat memilih metode lain untuk memperbarui URL, seperti:

this.router.navigate(
  [this.locationStrategy.path().split('?')[0]],
  {queryParams: queryParamsObj}
);

Dalam opsi ini browser Anda juga tidak menyegarkan tetapi URLperubahan Anda juga disuntikkan ke Routerdalam aplikasi Anda, jadi ketika Anda mengganti bahasa Anda tidak memiliki masalah seperti dalam this.location.replaceState().

Tentu saja Anda dapat memilih metode untuk kebutuhan Anda. Yang pertama lebih ringan karena Anda tidak menggunakan aplikasi Anda lebih dari perubahan URLdi browser.

kris_IV
sumber
3

Bagi saya itu sebenarnya adalah campuran keduanya dengan Angular 4.4.5.

Menggunakan router.navigate terus merusak url saya dengan tidak menghormati bagian realtiveTo: activatedRoute.

Saya telah berakhir dengan:

this._location.go(this._router.createUrlTree([this._router.url], { queryParams: { profile: value.id } }).toString())
Patrick P.
sumber
3

Gunakan atribut queryParamsHandling: 'merge' saat mengubah url.

this.router.navigate([], {
        queryParams: this.queryParams,
        queryParamsHandling: 'merge',
        replaceUrl: true,
});
Rajeev Raushan Prasad
sumber
3
Hal ini menyebabkan komponen yang saat ini dirutekan dimuat ulang
btx