Bagaimana cara mendapatkan permintaan kueri dari url di Angular 2?

237

Saya menggunakan angular2.0.0-beta.7. Ketika komponen dimuat pada jalur seperti /path?query=value1itu diarahkan ke /path. Mengapa paret GET dihapus? Bagaimana saya bisa mempertahankan parameter?

Saya memiliki kesalahan di router. Kalau saya punya rute utama suka

@RouteConfig([
  {
      path: '/todos/...',
      name: 'TodoMain',
      component: TodoMainComponent
  }
])

dan rute anak saya suka

@RouteConfig([
  { path: '/', component: TodoListComponent, name: 'TodoList', useAsDefault:true },
  { path: '/:id', component: TodoDetailComponent, name:'TodoDetail' }
])

maka saya tidak bisa mendapatkan params di TodoListComponent. Saya bisa mendapatkan

params("/my/path;param1=value1;param2=value2") 

tapi saya ingin yang klasik

query params("/my/path?param1=value1&param2=value2")
FireGM
sumber
1
bagaimana Anda menentukan @RouteConfigini path?
Pankaj Parkar
Saya menemukan kesalahan. Saya memiliki rute utama dan rute anak dan jika saya memiliki rute utama seperti {path: '/ todos / ...', nama: 'TodoMain', komponen: TodoMainComponent} dan rute anak {path: '/', komponen: TodoListComponent, name: 'TodoList', useAsDefault: true}, itu tidak berfungsi dan redirect ke url tanpa parry kueri.
FireGM

Jawaban:

412

Dengan menyuntikkan sebuah instance dari ActivatedRouteseseorang dapat berlangganan berbagai hal yang dapat diamati, termasuk a queryParamsdan yang paramsdapat diamati:

import {Router, ActivatedRoute, Params} from '@angular/router';
import {OnInit, Component} from '@angular/core';

@Component({...})
export class MyComponent implements OnInit {

  constructor(private activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    // Note: Below 'queryParams' can be replaced with 'params' depending on your requirements
    this.activatedRoute.queryParams.subscribe(params => {
        const userId = params['userId'];
        console.log(userId);
      });
  }

}

A CATATAN TENTANG TIDAK BERLAKU

@Reto dan @ codef0rmer dengan tepat menunjukkan bahwa, sesuai dokumen resmi, metode unsubscribe()komponen onDestroy()di dalam tidak diperlukan dalam kasus ini. Ini telah dihapus dari contoh kode saya. (lihat kotak lansiran biru di tutorial ini )

Stephen Paul
sumber
2
Saya selanjutnya menyarankan untuk mengganti langganan dengan janji - dalam kasus khusus ini. this.activatedRoute.params.toPromise () .then (response => ...) .catch (error => ...);
Desember
Di mana saya bisa melewati "activatedRoute"?
michali
20
Dari dokumentasi resmi: Apakah saya harus berhenti berlangganan? The Router manages the observables it provides and localizes the subscriptions. The subscriptions are cleaned up when the component is destroyed, protecting against memory leaks, so we don't need to unsubscribe from the route params Observable.
Reto
pengalihan sudut tanpa memecat langganan (atau janji). Saya dapat melihat callback oAUth asli dengan token, tetapi kemudian dialihkan ke rute tanpa params query dan console.log (param) hanyalah objek kosong.
FlavourScape
1
@Sobhan, ya ada perbedaan. Operator switchMap mengembalikan Observable sementara operator berlangganan memungkinkan pengamat (komponen kami) untuk melihat item yang akhirnya dipancarkan oleh Observable. Jadi dalam dokumen ada 2 contoh switchmap yang digunakan. 1) Mereka telah menggunakan switchMap untuk menambahkan permintaan untuk pahlawan. SwitchMap, tidak seperti berlangganan, akan memastikan bahwa permintaan dibatalkan jika pengguna menavigasi kembali ke rute sambil tetap mengambil pahlawan. 2) Pipa async digunakan. Pipa Async mengkonsumsi yang dapat diobservasi, jadi seseorang tidak boleh berlangganan (Pipa async akan melakukannya untuk Anda).
Stephen Paul
103

Ketika URL seperti ini http://stackoverflow.com?param1=value

Anda bisa mendapatkan param1 dengan kode ikuti:

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';

@Component({
    selector: '',
    templateUrl: './abc.html',
    styleUrls: ['./abc.less']
})
export class AbcComponent implements OnInit {
    constructor(private route: ActivatedRoute) { }

    ngOnInit() {
        // get param
        let param1 = this.route.snapshot.queryParams["param1"];
    }
}
Trung
sumber
2
apakah ini berarti Anda tidak perlu menambahkan "/: id" di jalur routeconfig lagi? karena saya mendapatkan "undefined" ketika saya menggunakan ini jadi saya masih harus memiliki kesalahan di suatu tempat
Axelle
2
Bagus. Ini yang saya cari karena saya perlu membaca params langsung dari url server dinamis. Saya tidak bisa menggunakan navigasi.
Tanggal
37

Meskipun pertanyaan menentukan versi beta 7 , pertanyaan ini juga muncul sebagai hasil pencarian teratas di Google untuk frasa umum seperti parameter kueri 2 sudut . Untuk alasan inilah inilah jawaban untuk router terbaru (saat ini dalam alpha.7 ).

Cara params dibaca telah berubah secara dramatis. Pertama, Anda perlu menyuntikkan dependensi yang dipanggil Routerdalam parameter konstruktor Anda seperti:

constructor(private router: Router) { }

dan setelah itu kita dapat berlangganan parameter kueri pada ngOnInitmetode kita (konstruktor juga boleh, tetapi ngOnInitharus digunakan untuk testabilitas) seperti

this.router
  .routerState
  .queryParams
  .subscribe(params => {
    this.selectedId = +params['id'];
  });

Dalam contoh ini kita membaca parameter id query dari URL like example.com?id=41.

Masih ada beberapa hal yang perlu diperhatikan:

  1. Mengakses properti paramssejenis params['id']selalu mengembalikan string , dan ini dapat dikonversi ke angka dengan awalan dengan +.
  2. Alasan mengapa kueri params diambil dengan diamati adalah bahwa ia memungkinkan menggunakan kembali contoh komponen yang sama alih-alih memuat yang baru. Setiap parameter kueri diubah, ini akan menyebabkan acara baru yang telah kami langgani dan karenanya kami dapat bereaksi terhadap perubahan tersebut.
Roope Hakulinen
sumber
Apakah ada cara untuk memiliki beberapa parameter ke anggota yang sama? Misalnya, saya ingin 'id' atau 'identifikasi' untuk membuka this.selectedId.
phandinhlan
@ phandinhlan: Yah, itu bukan pertanyaan yang terkait dengan Angular 2. Tentu saja dapat diimplementasikan, tetapi Anda perlu mendefinisikan sendiri logikanya. Pada dasarnya yang ingin Anda lakukan adalah memeriksa dulu apakah kunci pertama ditentukan dan baru kemudian membaca nilainya, dan jika tidak, baca nilainya dengan kunci lain. Ini bisa dicapai dengan sesuatu seperti if (params.hasOwnProperty('id')) { this.selectedId = params['id'] } else { this.selectedId = params['identification']}.
Roope Hakulinen
Ya saya akhirnya melakukan hal seperti itu. Saya hanya berpikir akan ada beberapa cara "built in" seperti: this.selectedId = + params ['id']; this.selectedId = + params ['identifikasi']; Tentu saja itu tidak masuk akal dan tidak berhasil.
phandinhlan
28

Saya benar-benar menyukai jawaban StevePaul tetapi kami dapat melakukan hal yang sama tanpa panggilan berlangganan / berhenti berlangganan yang asing.

import { ActivatedRoute } from '@angular/router';
constructor(private activatedRoute: ActivatedRoute) {
    let params: any = this.activatedRoute.snapshot.params;
    console.log(params.id);
    // or shortcut Type Casting
    // (<any> this.activatedRoute.snapshot.params).id
}
codef0rmer
sumber
7
peringatan tentu saja dengan yang satu ini adalah bahwa itu akan menjadi nilai awal dan perubahan selanjutnya tidak akan tercermin. Jadi, jika Anda mengubah parameter URL secara terprogram sebagai bagian dari logika Anda, itu adalah sesuatu yang perlu Anda ketahui
ambidexterous
Tidak yakin apakah ini berubah dengan versi Angular yang lebih baru, tetapi sekarang saya melihatnya di this.activatedRoute.snapshot.queryParams
Michael
21

Untuk mengirim parameter permintaan

import { Router } from '@angular/router';
this.router.navigate([ '/your-route' ], { queryParams: { key: va1, keyN: valN } });

Untuk menerima permintaan params

import { ActivatedRoute } from '@angular/router';
this.activatedRoute.queryParams.subscribe(params => {
    let value_1 = params['key'];
    let value_N = params['keyN'];
});

Sumber resmi

dddenis
sumber
Pembacaannya berfungsi dengan baik. Tapi ini case-sensitive. Bagaimana kita bisa membuatnya tidak sensitif huruf besar-kecil?
Unnie
12

Hai, Anda dapat menggunakan URLSearchParams, Anda dapat membaca lebih lanjut di sini .

impor:

import {URLSearchParams} from "@angular/http";

dan fungsi:

getParam(){
  let params = new URLSearchParams(window.location.search);
  let someParam = params.get('someParam');
  return someParam;
}

Perhatikan : Ini tidak didukung oleh semua platform dan tampaknya dalam kondisi "EKSPERIMENTAL" oleh dokumen sudut

Asaf Hananel
sumber
2
Ini tidak berhasil untuk saya. Saya telah menemukan bahwa window.location.search termasuk tanda tanya utama dari parameter querystring. Jadi, kunci untuk parameter pertama akan memiliki tanda tanya yang diawali.
AJ Morris
AJ Morris, untuk menyiasati masalah Anda: if (window.location.search.indexOf('?') == 0){ normalizedQueryString = window.location.search.substring(1); } else { normalizedQueryString = window.location.search; } let params = new URLSearchParams(normalizedQueryString);
ambidexterous
URLSearchParams sudah tidak digunakan lagi. Sekarang Anda dapat melakukannya dengan ActivatedRoute.
Robert Blasco Villarroya
7

Pertama, apa yang saya temukan bekerja dengan Angular2 adalah bahwa url dengan string kueri /path;query=value1

Untuk mengaksesnya dalam komponen yang Anda gunakan Begitu juga ini, tetapi sekarang ikuti blok kode:

    constructor(params: RouteParams){
    var val = params.get("query");
    }

Mengenai mengapa itu akan dihapus ketika Anda memuat komponen, itu bukan perilaku default. Saya memeriksa secara spesifik dalam proyek pengujian bersih dan tidak diarahkan atau diubah. Apakah ini rute default atau sesuatu yang khusus tentang perutean?

Baca tentang perutean dengan string kueri dan params di Tutorial Angular2 di https://angular.io/docs/ts/latest/guide/router.html#!#query-parameters

Namirna
sumber
Saya tidak dapat menggunakan params seperti "; param1 = value1; param2 = value2", tautan ini dibuat di situs lain dan mengarahkan ulang di situs saya seperti "example.com/auth?code_for_auth=askjfbkajdsbfksajdf"
FireGM
Cara routing diatur di Angular2 saat ini, saya pikir itu tidak mungkin. Beberapa jenis solusi akan diperlukan karena perutean anak tergantung pada url matriks. Adapun yang saya tahu setidaknya. Saya akan mencegatnya di server web saya dan mengubahnya sebagai retasan, menyebalkan tapi saya tidak bisa memikirkan cara lain saat ini
Namirna
Anda tidak memiliki kemungkinan untuk meminta situs yang menghubungkan untuk mengubah url mereka?
Namirna
1
Tidak. Tapi saya menyelesaikan masalah secara manual mengurai Location.path ()
FireGM
4
solusi ini sudah usang!
7

Anda bisa mendapatkan parameter kueri saat diteruskan ke dalam URL menggunakan ActivatedRoute seperti yang dinyatakan di bawah ini: -

url: - http: /domain.com? test = abc

import { Component } from '@angular/core';
import { ActivatedRoute }     from '@angular/router';

@Component({
  selector: 'my-home'
})
export class HomeComponent {

  constructor(private sharedServices : SharedService,private route: ActivatedRoute) { 
    route.queryParams.subscribe(
      data => console.log('queryParams', data['test']));
  }

}
Saurabh
sumber
7

Dapatkan param URL sebagai objek.

import { Router } from '@angular/router';
constructor(private router: Router) {
    console.log(router.parseUrl(router.url));
}
Jsonras
sumber
2

Jika Anda hanya ingin mendapatkan parameter kueri sekali, cara terbaik adalah menggunakan metode take sehingga Anda tidak perlu khawatir tentang berhenti berlangganan. Berikut ini cuplikan sederhana: -

constructor(private route: ActivatedRoute) {
  route.snapshot.queryParamMap.take(1).subscribe(params => {
     let category = params.get('category')
     console.log(category);
  })
}

Catatan: Hapus take (1) jika Anda ingin menggunakan nilai parameter di masa depan.

Abhishek Chandel
sumber
2

sekarang adalah:

this.activatedRoute.queryParams.subscribe((params: Params) => {
  console.log(params);
});
Alan
sumber
1
Terima kasih atas cuplikan kode ini, yang mungkin memberikan bantuan jangka pendek terbatas. Penjelasan yang tepat akan sangat meningkatkan nilai jangka panjangnya dengan menunjukkan mengapa ini adalah solusi yang baik untuk masalah ini dan akan membuatnya lebih bermanfaat bagi pembaca masa depan dengan pertanyaan lain yang serupa. Harap edit jawaban Anda untuk menambahkan beberapa penjelasan, termasuk asumsi yang Anda buat
Shawn C.
1

Saya harap ini akan membantu orang lain.

Pertanyaan di atas menyatakan bahwa nilai param query diperlukan setelah halaman dialihkan dan kita dapat mengasumsikan bahwa nilai snapshot (alternatif tanpa-pengamatan) akan cukup.

Tidak ada seorang pun di sini yang menyebutkan tentang snapshot.paramMap.get dari dokumentasi resmi .

this.route.snapshot.paramMap.get('id')

Jadi sebelum mengirimnya tambahkan ini dalam mengirim / mengarahkan kembali komponen:

import { Router } from '@angular/router';

kemudian arahkan kembali sebagai (didokumentasikan di sini ):

this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]);

atau hanya:

this.router.navigate(['/heroes', heroId ]);

Pastikan Anda telah menambahkan ini dalam modul perutean Anda seperti yang didokumentasikan di sini :

 { path: 'hero/:id', component: HeroDetailComponent }

Dan akhirnya, di komponen Anda yang perlu menggunakan parameter kueri

  • tambahkan impor (didokumentasikan di sini ):

    import { Router, ActivatedRoute, ParamMap } from '@angular/router';
  • menyuntikkan ActivatedRoute

(dokumentasi juga mengimpor switchMap dan juga menyuntikkan Router dan HeroService - tetapi mereka diperlukan hanya untuk alternatif yang dapat diamati - mereka TIDAK diperlukan ketika Anda menggunakan alternatif snapshot seperti dalam kasus kami):

    constructor(
      private route: ActivatedRoute
    ) {}
  • dan dapatkan nilai yang Anda butuhkan (didokumentasikan di sini ):

    ngOnInit() {
      const id = this.route.snapshot.paramMap.get('id');
    }

CATATAN: JIKA ANDA MENAMBAHKAN MODUL ROUTING PADA MODUL FITUR (SEPERTI YANG DITUNJUKKAN DALAM DOKUMENTASI) PASTIKAN BAHWA DALAM APLIKASI. MODEL ROUTING DATANG SEBELUM AppRoutingModule (atau file lain dengan rute aplikasi level root) DI IMPOR: []. FITUR LAINNYA ROUTES TIDAK AKAN DITEMUKAN (SEPERTI MEREKA AKAN DATANG SETELAH {path: '**', redirectTo: '/ not-found'} dan Anda hanya akan melihat pesan yang tidak ditemukan).

Ula
sumber
1

Anda hanya perlu menyuntikkan ActivatedRoute di konstruktor dan kemudian hanya mengakses params atau queryParams di atasnya

constructor(private route:ActivatedRoute){}
ngOnInit(){
        this.route.queryParams.subscribe(params=>{
        let username=params['username'];
      });
 }

Dalam beberapa kasus itu tidak memberikan apa pun di NgOnInit ... mungkin karena panggilan init sebelum inisialisasi params dalam kasus ini Anda dapat mencapai ini dengan meminta diamati untuk menunggu beberapa saat dengan fungsi debounceTime (1000)

misalnya =>

 constructor(private route:ActivatedRoute){}
    ngOnInit(){
            this.route.queryParams.debounceTime(100).subscribe(params=>{
            let username=params['username'];
          });
     }

debounceTime () Memancarkan nilai dari sumber yang dapat diamati hanya setelah rentang waktu tertentu berlalu tanpa emisi sumber lain

Rajiv
sumber
0

Anda tidak bisa mendapatkan parameter dari RouterState jika itu tidak ditentukan dalam rute, jadi dalam contoh Anda, Anda harus mengurai querystring ...

Berikut adalah kode yang saya gunakan:

let re = /[?&]([^=#&]+)=([^&#]*)/g;
let match;
let isMatch = true;
let matches = [];
while (isMatch) {
    match = re.exec(window.location.href);
    if (match !== null) {
        matches[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
        if (match.index === re.lastIndex) {
            re.lastIndex++;
        }
    }
    else {
        isMatch = false;
    }
}
console.log(matches);

Julien Ricard
sumber
0

Kueri dan Path (Sudut 8)

Jika Anda memiliki url seperti https://myapp.com/owner/123/show?height=23 lalu gunakan

combineLatest( [this.route.paramMap, this.route.queryParamMap] )
  .subscribe( ([pathParams, queryParams]) => {
    let ownerId = pathParams.get('ownerId');    // =123
    let height  = queryParams.get('height');    // =height
    // ...
  })

MEMPERBARUI

Dalam kasus ketika Anda menggunakan this.router.navigate([yourUrl]);dan parameter kueri Anda tertanam dalam yourUrlstring kemudian sudut menyandikan URL dan Anda mendapatkan sesuatu seperti ini https://myapp.com/owner/123/show%3Fheight%323 - dan solusi di atas akan memberikan hasil yang salah ( queryParams akan kosong, dan params kueri dapat direkatkan ke param path terakhir jika ada di ujung path). Dalam hal ini ubah cara navigasi ke ini

this.router.navigateByUrl(yourUrl);
Kamil Kiełczewski
sumber