วิธีรับพารามิเตอร์แบบสอบถามจาก url ใน Angular 2


237

ฉันใช้ angular2.0.0-beta.7 เมื่อองค์ประกอบที่มีการโหลดบนเส้นทางเช่นมันจะถูกเปลี่ยนเส้นทางไปยัง/path?query=value1 /pathทำไม GET params ถูกนำออก? ฉันจะรักษาพารามิเตอร์ไว้ได้อย่างไร?

ฉันมีข้อผิดพลาดในเราเตอร์ ถ้าฉันมีเส้นทางหลักเช่น

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

และเส้นทางลูกของฉันเช่น

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

จากนั้นฉันไม่สามารถรับพารามิเตอร์ใน TodoListComponent ฉันสามารถที่จะรับ

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

แต่ฉันต้องการความคลาสสิค

query params("/my/path?param1=value1&param2=value2")

1
คุณระบุ@RouteConfigเรื่องนี้pathอย่างไร
Pankaj Parkar

ฉันพบข้อผิดพลาด ฉันมีเส้นทางหลักและเส้นทางเด็กและหากฉันมีเส้นทางหลักเช่น {path: '/ todos / ... ', ชื่อ: 'TodoMain', คอมโพเนนต์: TodoMainComponent} และเส้นทางเด็ก {path: '/', ส่วนประกอบ: TodoListComponent, ชื่อ: 'TodoList', useAsDefault: true}, มันใช้งานไม่ได้และเปลี่ยนเส้นทางไปยัง url โดยไม่มี params ของแบบสอบถาม
FireGM

คำตอบ:


412

ด้วยการฉีดอินสแตนซ์ของสิ่งActivatedRouteหนึ่งสามารถติดตามความหลากหลายของสิ่งที่สามารถสังเกตได้รวมถึง a queryParamsและสิ่งที่paramsสังเกตได้:

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

}

หมายเหตุเกี่ยวกับการปฏิเสธความรับผิดชอบ

@Reto และ @ codef0rmer ได้ชี้ให้เห็นอย่างถูกต้องว่าตามเอกสารอย่างเป็นทางการแล้ววิธีการunsubscribe()ในส่วนประกอบonDestroy()ไม่จำเป็นในกรณีนี้ สิ่งนี้ถูกลบออกจากตัวอย่างรหัสของฉัน (ดูช่องการแจ้งเตือนสีน้ำเงินในบทช่วยสอนนี้ )


2
ฉันขอแนะนำให้แทนที่การสมัครสมาชิกด้วยสัญญา - ในกรณีพิเศษนี้ this.activatedRoute.params.toPromise () .then (response => ... ) .catch (ข้อผิดพลาด => ... );
ธ.ค.

ฉันจะผ่าน "enableRoute" ได้ที่ไหน
michali

20
จากเอกสารอย่างเป็นทางการ: ฉันจำเป็นต้องยกเลิกการสมัครหรือไม่? 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

เปลี่ยนเส้นทางเชิงมุมโดยไม่ต้องสมัครสมาชิก (หรือสัญญา) ฉันสามารถเห็นการโทรกลับ oAUth ดั้งเดิมด้วยโทเค็น แต่จากนั้นมันจะเปลี่ยนเส้นทางไปยังเส้นทางที่ไม่มี params แบบสอบถามและ console.log (param) เป็นเพียงวัตถุว่างเปล่า
FlavourScape

1
@Shanhan ใช่มีความแตกต่าง ตัวดำเนินการ switchMap ส่งคืน Observable ในขณะที่โอเปอเรเตอร์สมัครสมาชิกอนุญาตให้ผู้สังเกตการณ์ (ส่วนประกอบของเรา) เห็นรายการที่ถูกปล่อยออกมาในที่สุดโดย Observable ดังนั้นในเอกสารมีการใช้ switchmap 2 อินสแตนซ์ 1) พวกเขาใช้ switchMap เพื่อผนวกคำขอสำหรับ heros SwitchMap ซึ่งแตกต่างจากการสมัครสมาชิกจะให้แน่ใจว่าคำขอถูกยกเลิกหากผู้ใช้นำทางไปยังเส้นทางในขณะที่ยังคงเรียกฮีโร่ 2) ใช้ async pipe ท่อ Async กินสิ่งที่สังเกตได้ดังนั้นจึงต้องไม่สมัครสมาชิก (ท่อ async จะทำเพื่อคุณ)
สตีเฟ่นพอล

103

เมื่อ URL เช่นนี้ http://stackoverflow.com?param1=value

คุณสามารถรับ param1 ด้วยรหัสตาม:

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"];
    }
}

2
หมายความว่าคุณไม่จำเป็นต้องเพิ่ม "/: id" ในเส้นทาง routeconfig อีกต่อไปหรือไม่ เพราะฉันได้รับ "undefined" เมื่อฉันใช้สิ่งนี้ดังนั้นฉันยังต้องมีข้อผิดพลาดอยู่ที่ไหน
ซัก

2
ยิ่งใหญ่ นี่คือฉันกำลังมองหาเพราะฉันต้องอ่านพารามิเตอร์โดยตรงจาก URL เซิร์ฟเวอร์แบบไดนามิก ฉันไม่สามารถใช้การนำทาง
.Bear

37

แม้ว่าคำถามระบุรุ่นเบต้า 7คำถามนี้ขึ้นมาเป็นผลการค้นหาบน Google สำหรับวลีที่เหมือนกันเช่นเชิงมุม 2 พารามิเตอร์การค้นหา ด้วยเหตุนี้นี่คือคำตอบสำหรับเราเตอร์ใหม่ล่าสุด (ในปัจจุบัน alpha.7 )

วิธีการอ่านพารามิเตอร์มีการเปลี่ยนแปลงอย่างมาก ก่อนอื่นคุณต้องฉีดการพึ่งพาที่เรียกRouterในพารามิเตอร์ตัวสร้างของคุณเช่น:

constructor(private router: Router) { }

และหลังจากนั้นเราสามารถสมัครสมาชิกพารามิเตอร์การสืบค้นในngOnInitวิธีการของเรา(คอนสตรัคก็โอเคเกินไป แต่ngOnInitควรจะใช้สำหรับการทดสอบ) เช่น

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

ในตัวอย่างนี้เราอ่านid param idจาก URL example.com?id=41เช่น

ยังมีบางสิ่งที่สังเกตเห็น:

  1. การเข้าถึงคุณสมบัติของparamsLike params['id']จะส่งคืนสตริงเสมอและสิ่งนี้สามารถแปลงเป็นตัวเลขได้โดย prefixing +ด้วย
  2. เหตุผลที่ทำให้การสืบค้นพารามิเตอร์ดึงข้อมูลได้ด้วยการสังเกตคือช่วยให้สามารถใช้อินสแตนซ์องค์ประกอบเดียวกันได้อีกครั้งแทนที่จะโหลดขึ้นมาใหม่ แต่ละครั้งที่พารามิเตอร์การค้นหาเปลี่ยนแปลงจะทำให้เกิดเหตุการณ์ใหม่ที่เราสมัครเป็นสมาชิกและทำให้เราสามารถตอบสนองต่อการเปลี่ยนแปลงตามลำดับ

มีวิธีการที่จะให้หลายพารามิเตอร์เป็นสมาชิกเดียวกันหรือไม่? ตัวอย่างเช่นฉันต้องการ 'id' หรือ 'บัตรประจำตัว' เพื่อไปที่ this.selectedId
phandinhlan

@phandinhlan: นั่นไม่ใช่คำถามที่เกี่ยวข้องกับ Angular 2 แน่นอนสามารถนำไปใช้ได้ แต่คุณต้องกำหนดตรรกะด้วยตัวเอง โดยทั่วไปสิ่งที่คุณต้องการทำคือการตรวจสอบก่อนว่ามีการกำหนดคีย์แรกและจากนั้นอ่านค่าจากนั้นและถ้าไม่ให้อ่านค่าด้วยคีย์อื่น if (params.hasOwnProperty('id')) { this.selectedId = params['id'] } else { this.selectedId = params['identification']}นี้จะประสบความสำเร็จกับสิ่งที่ต้องการ
Roope Hakulinen

ใช่ฉันลงเอยด้วยการทำอะไรแบบนั้น ฉันแค่คิดว่าจะมีบางอย่าง "ใน" เช่น: this.selectedId = + params ['id']; this.selectedId = + params ['identification']; แน่นอนว่าไม่ได้มีเหตุผลและไม่ได้ผล
phandinhlan

28

ฉันชอบคำตอบของ @ StevePaul จริง ๆ แต่เราสามารถทำเช่นเดียวกันได้โดยไม่ต้องโทรออก / ยกเลิกการเป็นสมาชิกภายนอก

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
}

7
คำเตือนของหลักสูตรนี้คือมันจะเป็นค่าเริ่มต้นและการเปลี่ยนแปลงที่ตามมาจะไม่สะท้อนให้เห็น ดังนั้นหากคุณเปลี่ยนพารามิเตอร์ URL โดยทางโปรแกรมซึ่งเป็นส่วนหนึ่งของตรรกะของคุณนั่นเป็นสิ่งที่คุณต้องระวัง
ambidexterous

ไม่แน่ใจว่าสิ่งนี้เปลี่ยนไปด้วย Angular รุ่นที่ใหม่กว่าหรือไม่ แต่ตอนนี้ฉันเห็นในนี้แล้วเปิดใช้งาน Route.snapshot.queryParams
Michael

21

ในการส่ง params แบบสอบถาม

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

เพื่อรับ params แบบสอบถาม

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

แหล่งข้อมูลอย่างเป็นทางการ


การอ่านทำงานได้ดี แต่เป็นแบบตรงตัวอักษร เราจะทำให้เป็นกรณีที่ไม่รู้สึกได้อย่างไร
Unnie

12

สวัสดีคุณสามารถใช้ URLSearchParams คุณสามารถอ่านเพิ่มเติมได้ที่นี่

การนำเข้า:

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

และฟังก์ชั่น:

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

ประกาศ : ระบบนี้ไม่รองรับทุกแพลตฟอร์มและดูเหมือนว่าจะอยู่ในสถานะ "EXPERIMENTAL" โดยเอกสารเชิงมุม


2
มันไม่ได้ผลสำหรับฉัน ฉันพบว่า window.location.search มีเครื่องหมายคำถามนำหน้าของพารามิเตอร์การสืบค้น ดังนั้นคีย์สำหรับพารามิเตอร์แรกจะมีเครื่องหมายคำถามเสริมไว้
AJ Morris

AJ Morris เพื่อแก้ไขปัญหาของคุณ: if (window.location.search.indexOf('?') == 0){ normalizedQueryString = window.location.search.substring(1); } else { normalizedQueryString = window.location.search; } let params = new URLSearchParams(normalizedQueryString);
ตีสองหน้า

URLSearchParams มันเลิกใช้แล้ว ตอนนี้คุณสามารถทำได้ด้วย ActivatedRoute
Robert Blasco Villarroya

7

ก่อนอื่นสิ่งที่ฉันได้พบกับการทำงานกับ Angular2 คือ URL ที่มีสตริงแบบสอบถามจะเป็น /path;query=value1

หากต้องการเข้าถึงในองค์ประกอบที่คุณใช้ดังนั้นนี่คือตอนนี้ แต่ตามบล็อกรหัส:

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

สำหรับสาเหตุที่จะถูกลบเมื่อคุณโหลดส่วนประกอบนั่นไม่ใช่พฤติกรรมเริ่มต้น ฉันตรวจสอบเฉพาะในโครงการทดสอบที่สะอาดและไม่ได้เปลี่ยนเส้นทางหรือเปลี่ยนแปลง มันเป็นเส้นทางเริ่มต้นหรืออย่างอื่นที่พิเศษเกี่ยวกับเส้นทางหรือไม่

อ่านเกี่ยวกับการกำหนดเส้นทางด้วยสตริงการสืบค้นและ params ในบทเรียน Angular2 ที่https://angular.io/docs/ts/latest/guide/router.html#!#query-parameters


ฉันไม่สามารถใช้พารามิเตอร์เช่น "; param1 = value1; param2 = value2" ลิงก์นี้สร้างขึ้นในเว็บไซต์อื่นและเปลี่ยนเส้นทางบนเว็บไซต์ของฉันเช่น "example.com/auth?code_for_auth=askjfbkajdsbfksajdf"
FireGM

วิธีการตั้งค่าเส้นทางใน Angular2 ในตอนนี้ฉันไม่คิดว่ามันจะเป็นไปได้จริง ๆ วิธีแก้ปัญหาบางอย่างเป็นสิ่งจำเป็นเนื่องจากการกำหนดเส้นทางเด็กจะขึ้นอยู่กับเมทริกซ์ url สำหรับอย่างที่ฉันรู้อย่างน้อย ฉันจะตัดมันที่เว็บเซิร์ฟเวอร์ของฉันและแปลงเป็นแฮ็ค แต่ฉันไม่สามารถคิดวิธีอื่นได้ในขณะนี้
Namirna

คุณไม่มีความเป็นไปได้ที่จะขอให้เว็บไซต์ลิงค์เปลี่ยน URL
Namirna

1
ไม่ แต่ฉันแก้ไขปัญหาได้อย่างง่ายดายเพียงแค่แยก Location.path ()
FireGM

4
โซลูชันนี้เลิกใช้แล้ว!

7

คุณสามารถรับพารามิเตอร์การสืบค้นเมื่อส่งผ่าน URL โดยใช้ ActivatedRoute ตามที่ระบุไว้ด้านล่าง: -

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

}

7

รับพารามิเตอร์ URL เป็นวัตถุ

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

2

ถ้าคุณต้องการที่จะได้รับพารามิเตอร์การค้นหาครั้งวิธีที่ดีที่สุดคือการใช้ใช้วิธีการเพื่อให้คุณไม่ต้องกังวลเกี่ยวกับการยกเลิก นี่คือตัวอย่างง่ายๆ: -

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

หมายเหตุ:ลบtake (1)หากคุณต้องการใช้ค่าพารามิเตอร์ในอนาคต


2

ตอนนี้มันเป็น:

this.activatedRoute.queryParams.subscribe((params: Params) => {
  console.log(params);
});

1
ขอบคุณสำหรับข้อมูลโค้ดนี้ซึ่งอาจให้ความช่วยเหลือระยะสั้นแบบ จำกัด คำอธิบายที่เหมาะสมจะช่วยเพิ่มมูลค่าในระยะยาวได้อย่างมากโดยการแสดงว่าทำไมนี่จึงเป็นทางออกที่ดีสำหรับปัญหาและจะทำให้มีประโยชน์มากขึ้นสำหรับผู้อ่านในอนาคตด้วยคำถามอื่น ๆ ที่คล้ายกัน โปรดแก้ไขคำตอบของคุณเพื่อเพิ่มคำอธิบายรวมถึงข้อสันนิษฐานที่คุณเคยทำ
Shawn C.

1

ฉันหวังว่ามันจะช่วยคนอื่น

คำถามข้างต้นระบุว่าจำเป็นต้องใช้ค่าพารามิเตอร์การสืบค้นหลังจากหน้าถูกเปลี่ยนเส้นทางและเราสามารถสรุปได้ว่าค่าสแนปชอต (ทางเลือกที่ไม่สามารถสังเกตเห็นได้) นั้นเพียงพอแล้ว

ไม่มีใครที่นี่กล่าวถึงเกี่ยวกับ snapshot.paramMap.get จากเอกสารที่เป็นทางการ

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

ดังนั้นก่อนที่จะส่งมันเพิ่มสิ่งนี้ในการส่ง / การกำกับส่วนประกอบ:

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

จากนั้นสั่งใหม่เป็นอย่างใดอย่างหนึ่ง (จัดทำเป็นเอกสารไว้ที่นี่ ):

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

หรือเพียงแค่:

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

ตรวจสอบให้แน่ใจว่าคุณได้เพิ่มสิ่งนี้ไว้ในโมดูลการเราต์ตามที่บันทึกไว้ที่นี่ :

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

และในที่สุดในองค์ประกอบของคุณซึ่งจำเป็นต้องใช้พารามิเตอร์การสืบค้น

  • เพิ่มการนำเข้า (มีเอกสารที่นี่ ):

    import { Router, ActivatedRoute, ParamMap } from '@angular/router';
  • ฉีด ActivatedRoute

(เอกสารยังนำเข้า switchMap และฉีดเร้าเตอร์และ HeroService - แต่จำเป็นสำหรับทางเลือกที่สังเกตได้เท่านั้น - ไม่จำเป็นเมื่อคุณใช้สแนปชอตทางเลือกเช่นในกรณีของเรา):

    constructor(
      private route: ActivatedRoute
    ) {}
  • และรับค่าที่คุณต้องการ (จัดทำเป็นเอกสารไว้ที่นี่ ):

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

หมายเหตุ: หากคุณเพิ่มโมดูลการเดินทางไปยังโมดูลคุณสมบัติ (แสดงให้เห็นในเอกสาร) ให้แน่ใจว่าใน APP.MODULE.ts ที่โมดูลการเดินทางมาก่อน AppRoutingModule (หรือไฟล์อื่น ๆ ที่มีเส้นทางแอประดับราก) ในการนำเข้า: [] เส้นทางคุณสมบัติอื่นจะไม่พบ (ตามที่พวกเขาจะมาหลังจาก {เส้นทาง: '**', redirectTo: '/ ไม่พบ'} และคุณจะเห็นข้อความที่ไม่พบเท่านั้น)


1

คุณเพียงแค่ต้องฉีด ActivatedRoute ในคอนสตรัคเตอร์จากนั้นก็เข้าถึง params หรือ queryParams

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

ในบางกรณีมันไม่ได้ให้อะไรใน NgOnInit ... อาจเป็นเพราะการเรียก init ก่อนที่จะเริ่มต้น params ในกรณีนี้คุณสามารถทำได้โดยขอให้สามารถสังเกตได้รอฟังก์ชั่น debounceTime (1000)

เช่น =>

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

debounceTime () ปล่อยค่าจากแหล่งที่สังเกตได้เฉพาะหลังจากช่วงเวลาเฉพาะผ่านไปโดยไม่มีการปล่อยแหล่งที่มาอื่น


0

คุณไม่สามารถรับพารามิเตอร์จาก RouterState หากไม่ได้กำหนดไว้ในเส้นทางดังนั้นในตัวอย่างของคุณคุณต้องแยกวิเคราะห์ข้อความ ...

นี่คือรหัสที่ฉันใช้:

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


0

ข้อความค้นหาและเส้นทาง (เชิงมุม 8)

หากคุณมี URL เช่นhttps://myapp.com/owner/123/show?height=23 ให้ใช้

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

UPDATE

ในกรณีที่คุณใช้this.router.navigate([yourUrl]);และพารามิเตอร์การสืบค้นของคุณฝังอยู่ในyourUrlสตริงแล้ว angular เข้ารหัส URL และคุณได้รับสิ่งนี้https://myapp.com/owner/123/show%3Fheight%323-และวิธีการแก้ปัญหาข้างต้นจะให้ผลที่ไม่ถูกต้อง ( queryParams จะว่างเปล่าและพารามิเตอร์การสืบค้นสามารถติดกาวกับพา ธ สุดท้ายของพารามิเตอร์หากอยู่บนปลายพา ธ ) ในกรณีนี้ให้เปลี่ยนวิธีนำทางไปยังสิ่งนี้

this.router.navigateByUrl(yourUrl);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.