Angular: วิธีอัปเดต queryParams โดยไม่ต้องเปลี่ยนเส้นทาง


128

ฉันกำลังพยายามอัปเดต (เพิ่มลบ) queryParams จากส่วนประกอบ ใน angularJS มันเคยเป็นไปได้ด้วย:

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

ฉันมีแอพที่มีรายการที่ผู้ใช้สามารถกรองสั่งซื้อ ฯลฯ และฉันต้องการตั้งค่าใน queryParams ของ url ตัวกรองทั้งหมดที่เปิดใช้งานเพื่อให้เขาสามารถคัดลอก / วาง url หรือแชร์กับคนอื่นได้

อย่างไรก็ตามฉันไม่ต้องการให้โหลดหน้าซ้ำทุกครั้งที่เลือกตัวกรอง

สิ่งนี้ใช้ได้กับเราเตอร์ใหม่หรือไม่?

คำตอบ:


274

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

สิ่งที่ต้องการ (ในส่วนประกอบ):

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

โปรดทราบว่าแม้ว่าจะไม่โหลดหน้าซ้ำ แต่ก็จะดันรายการใหม่ไปยังประวัติของเบราว์เซอร์ { queryParams: queryParams, replaceUrl: true }หากคุณต้องการที่จะแทนที่ในประวัติศาสตร์แทนการเพิ่มค่าใหม่มีคุณสามารถใช้

แก้ไข: ตามที่ระบุไว้แล้วในความคิดเห็น[]และrelativeToคุณสมบัติขาดหายไปในตัวอย่างเดิมของฉันดังนั้นจึงอาจเปลี่ยนเส้นทางได้เช่นกันไม่ใช่แค่พารามิเตอร์การสืบค้น การthis.router.navigateใช้งานที่เหมาะสมจะอยู่ในกรณีนี้:

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

การตั้งค่าพารามิเตอร์ใหม่เป็นnullจะลบพารามิเตอร์ออกจาก URL


30
ฉันต้องใช้[]แทน['.']เพื่อให้มันใช้งานได้
Jaime Gómez

5
จำเป็นต้องใช้ queryParams ['relativeTo'] = this.activatedRoute; เพื่อให้การนำทางสัมพันธ์กับหน้าปัจจุบัน
klonq

3
ทางออกที่ดีสำหรับการแก้ปัญหาของ OP สิ่งที่ไม่ได้รับคุณเว้นแต่ฉันจะพลาดบางอย่างคือความสามารถในการย้อนกลับและไปข้างหน้าในประวัติของหน้าปัจจุบันของคุณ (เช่นเปลี่ยนตัวกรองหรือลำดับ 5 ครั้งแต่ละรายการมี URL ของตัวเอง แต่มีส่วนประกอบเดียวกัน) และมี เนื้อหาของหน้าจะเป็นอย่างไรหากคุณเข้าถึง URL ทั้ง 5 นี้โดยตรง ฉันคิดว่าคุณสามารถทำสิ่งนี้ให้สำเร็จได้ด้วยตนเองthis.activatedRoute.queryParams.subscribeและทำการอัปเดตต่างๆในส่วนประกอบของคุณ แต่มีวิธี Angular ง่ายๆในการโหลดเส้นทางเพื่อให้ย้อนกลับและไปข้างหน้าโดยอัตโนมัติหรือไม่?
jmq

1
เมื่อใช้ router.navigate มันจะเลื่อนขึ้นด้านบนของหน้าต่างมีแนวคิดอย่างไรในการปิดใช้งานสิ่งนี้
Hese

1
@ เฮียแน่ใจเหรอ? ฉันไม่คิดว่ามันจะเลื่อนขึ้นไปด้านบน โปรดดูตัวอย่างนี้stackblitz.com/edit/angular-sdtsew?file=src/app/…
Radosław Roszkowiak

23

คำตอบของ @ Radosław Roszkowiak เกือบจะถูกต้องยกเว้นที่relativeTo: this.routeจำเป็นดังต่อไปนี้:

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

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

14

ใน Angular 5 คุณสามารถรับและแก้ไขสำเนาของurlTreeได้อย่างง่ายดายโดยการแยกวิเคราะห์ url ปัจจุบัน ซึ่งจะรวมพารามิเตอร์และส่วนย่อยของแบบสอบถาม

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

  this.router.navigateByUrl(urlTree); 

ว่า "วิธีที่ถูกต้อง" ในการปรับเปลี่ยนพารามิเตอร์การค้นหาน่าจะเป็นกับ createUrlTreeเช่นนี้ซึ่งจะสร้าง UrlTree ใหม่จากปัจจุบันในขณะที่ให้เราปรับเปลี่ยนโดยใช้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); 
}

เพื่อที่จะเอาแบบสอบถามพารามิเตอร์วิธีนี้คุณสามารถตั้งค่าให้หรือundefinednull


2
navigateByUrlแตกต่างจากnavigate- ไม่ใช่เฉพาะกับพารามิเตอร์ UrlTree ดูstackoverflow.com/a/45025432/271012
Drenai

9

ลอง

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

จะทำงานสำหรับการนำทางในเส้นทางเดียวกันนอกเหนือจากเครื่องหมายคำพูดเดี่ยว


ฉันกำลังมองหาสิ่งที่แน่นอนนี้ ขอบคุณ!!!
cevaris

7

คำตอบที่มีการโหวตส่วนใหญ่ใช้ได้ผลกับฉันบางส่วน URL ของเบราว์เซอร์ยังคงเหมือนเดิม แต่ของฉันใช้งานrouterLinkActiveไม่ได้อีกต่อไปหลังจากการนำทาง

วิธีแก้ปัญหาของฉันคือใช้ 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());
  }
}

ฉันใช้ HttpParams เพื่อสร้างสตริงการสืบค้นเนื่องจากฉันใช้มันเพื่อส่งข้อมูลด้วย httpClient อยู่แล้ว แต่คุณสามารถสร้างมันเองได้

และthis._router.url.split("?")[0]คือการลบสตริงการสืบค้นก่อนหน้าทั้งหมดออกจาก url ปัจจุบัน


4
นี่ควรเป็นคำตอบที่ยอมรับเราเตอร์ยังรีเฟรช ngOnit, location.go ไม่ได้ทำเช่นนี้! สิ่งนี้สำคัญมากเพราะถ้าคอมโพเนนต์ของคุณทำ ngOnit logic (การโทร HTTP เป็นต้น) พวกเขาจะถูกเรียกอีกครั้งเมื่อคุณใช้ router.navigate คุณไม่ต้องการสิ่งนี้
Danny Hoeve

ทำไมคุณต้องใช้เราเตอร์สำหรับ url เท่านั้น ไม่this.location.path().split...ดีกว่าเหรอ
Vladimir

@ Vladimir คุณพูดถูกฉันใช้มันเพื่อจุดประสงค์อื่นในส่วนประกอบของฉันดังนั้นมันจึงไม่เพียงแค่นั้น ฉันไม่มีเวลาตรวจสอบแม้ว่า
moi_meme

สิ่งนี้จะใช้ไม่ได้หากคุณต้องการเก็บรักษาพารามิเตอร์การค้นหาเช่นการส่งเสริมการขายหรือพารามิเตอร์ติดตามของ Google
Jon Tinsman

6

ฉันลงเอยurlTreeด้วยการรวมกับlocation.go

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

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

ไม่แน่ใจว่าtoStringอาจทำให้เกิดปัญหาได้หรือไม่ แต่น่าเสียดายที่location.goดูเหมือนจะเป็นสตริง


4

หากคุณต้องการเปลี่ยนพารามิเตอร์การสืบค้นโดยไม่ต้องเปลี่ยนเส้นทาง ดูตัวอย่างด้านล่างอาจช่วยคุณได้: เส้นทางปัจจุบันคือ: / search & Target route is (without reload page): / search? query = love

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

โปรดทราบ: คุณสามารถใช้this.router.navigate (['search']แทนthis.router.navigate (['.']


ฉันไม่แน่ใจว่า [.] เป็นแนวทางที่ดีกว่าrelativeTo:แต่วิธี.then()นี้มีประโยชน์ - ไม่ทราบว่า nav () ส่งคืนสัญญาดีใจมากที่คุณโพสต์!
Drenai

0

ขั้นแรกเราต้องนำเข้าโมดูลเราเตอร์จากเราเตอร์เชิงมุมและประกาศชื่อนามแฝง

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

1. คุณสามารถเปลี่ยนพารามิเตอร์การสืบค้นได้โดยใช้ฟังก์ชัน "router.navigate" และส่งผ่านพารามิเตอร์การสืบค้น

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

จะอัปเดตพารามิเตอร์การสืบค้นในเส้นทางที่เปิดใช้งานเช่นปัจจุบัน

  1. ด้านล่างนี้จะเปลี่ยนเส้นทางไปยังหน้า abc โดยมี _id, วันและชื่อเป็นพารามิเตอร์ข้อความค้นหา

    this.router.navigate (['/ abc'], {queryParams: {_id: "abc", วัน: "1", ชื่อ: "dfd"}});

    จะอัปเดตพารามิเตอร์การสืบค้นในเส้นทาง "abc" พร้อมกับพารามิเตอร์แบบสอบถามสามตัว

สำหรับการดึงพารามิเตอร์แบบสอบถาม: -

    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
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.