Angular: Cách cập nhật queryParams mà không cần thay đổi tuyến đường


125

Tôi đang cố gắng cập nhật (thêm, xóa) queryParams từ một thành phần. Trong angleJS, nó từng có thể thực hiện được nhờ:

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

Tôi có một ứng dụng với danh sách mà người dùng có thể lọc, đặt hàng, v.v. và tôi muốn đặt trong queryParams của url tất cả các bộ lọc được kích hoạt để anh ta có thể sao chép / dán url hoặc chia sẻ nó với người khác.

Tuy nhiên, tôi không muốn tải lại trang của mình mỗi khi bộ lọc được chọn.

Điều này có khả thi với bộ định tuyến mới không?

Câu trả lời:


270

Bạn có thể điều hướng đến tuyến đường hiện tại với các tham số truy vấn mới, điều này sẽ không tải lại trang của bạn, nhưng sẽ cập nhật các tham số truy vấn.

Một cái gì đó như (trong thành phần):

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

Lưu ý rằng trong khi nó sẽ không tải lại trang, nó sẽ đẩy một mục mới vào lịch sử của trình duyệt. Nếu bạn muốn thay thế nó trong lịch sử thay vì thêm giá trị mới vào đó, bạn có thể sử dụng { queryParams: queryParams, replaceUrl: true }.

CHỈNH SỬA: Như đã được chỉ ra trong các nhận xét, []và thuộc relativeTotính bị thiếu trong ví dụ ban đầu của tôi, vì vậy nó cũng có thể thay đổi tuyến đường, không chỉ tham số truy vấn. Cách this.router.navigatesử dụng thích hợp sẽ là trong trường hợp này:

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

Đặt giá trị tham số mới thành nullsẽ xóa tham số khỏi URL.


30
Tôi đã phải sử dụng []thay vì ['.']để làm cho nó làm việc
Jaime Gómez

5
Cần sử dụng queryParams ['relativeTo'] = this.actiisedRoute; để thực hiện điều hướng liên quan đến trang hiện tại
klonq

3
Giải pháp tốt để giải quyết vấn đề của OP. Điều mà nó không giúp bạn hiểu được, trừ khi tôi thiếu thứ gì đó, là khả năng quay lui và chuyển tiếp trong lịch sử trang hiện tại của bạn (ví dụ: bộ lọc hoặc thứ tự đã thay đổi 5 lần, mỗi lần có URL riêng nhưng cùng một thành phần) và có nội dung của trang sẽ hiển thị như thế nào nếu bạn truy cập trực tiếp vào 5 URL đó. Tôi nghĩ rằng bạn có thể thực hiện thủ công điều này thông qua this.activatedRoute.queryParams.subscribevà thực hiện các cập nhật khác nhau trong thành phần của mình, nhưng có cách Angular đơn giản nào để chỉ tải tuyến đường sao cho quay lại và chuyển tiếp sẽ hoạt động tự động không?
jmq

1
khi sử dụng router.navigate, nó sẽ cuộn lên trên cùng của cửa sổ, bạn có ý kiến ​​gì về cách vô hiệu hóa điều này không?
Hese

1
@Hese, bạn có chắc không? Tôi không nghĩ nó sẽ cuộn lên trên cùng. Vui lòng xem ví dụ này: stackblitz.com/edit/angular-sdtsew?file=src/app/…
Radosław Roszkowiak

23

Câu trả lời của @ Radosław Roszkowiak gần như đúng ngoại trừ điều đó relativeTo: this.routeđược yêu cầu như sau:

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

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

14

Trong Angular 5, bạn có thể dễ dàng lấy và sửa đổi bản sao của urlTree bằng cách phân tích cú pháp url hiện tại. Điều này sẽ bao gồm các tham số và phân đoạn truy vấn.

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

  this.router.navigateByUrl(urlTree); 

"Cách đúng" để sửa đổi tham số truy vấn có thể là với createUrlTree như bên dưới, tạo một UrlTree mới từ hiện tại trong khi cho phép chúng tôi sửa đổi nó bằng 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); 
}

Để xóa tham số truy vấn theo cách này, bạn có thể đặt nó thành undefinedhoặc null.


2
navigateByUrlkhác với navigate- không chỉ với tham số UrlTree. Xem stackoverflow.com/a/45025432/271012
Drenai

9

Thử

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

sẽ hoạt động cho điều hướng tuyến đường tương tự ngoài dấu ngoặc kép.


Tôi đã tìm kiếm điều này chính xác. Cảm ơn bạn!!!
cevaris

7

Câu trả lời với hầu hết phiếu bầu một phần phù hợp với tôi. Url của trình duyệt vẫn giữ nguyên nhưng của tôi routerLinkActivekhông còn hoạt động sau khi điều hướng.

Giải pháp của tôi là sử dụng 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());
  }
}

Tôi đã sử dụng HttpParams để xây dựng chuỗi truy vấn vì tôi đã sử dụng nó để gửi thông tin với httpClient. nhưng bạn chỉ có thể tự xây dựng nó.

this._router.url.split("?")[0], là xóa tất cả chuỗi truy vấn trước đó khỏi url hiện tại.


4
Đây NÊN là câu trả lời được chấp nhận, router.navigates cũng làm mới ngOnit, location.go KHÔNG làm điều này! Điều này thực sự quan trọng vì nếu thành phần của bạn thực hiện một số logic ngOnit (các cuộc gọi HTTP, v.v.) thì chúng sẽ được gọi lại khi bạn sử dụng router.navigate. Bạn không muốn điều này.
Danny Hoeve

Tại sao bạn cần bộ định tuyến, chỉ dành cho url? Không this.location.path().split...tốt hơn sao?
Vladimir

@Vladimir bạn có thể đúng, tôi đã sử dụng nó cho mục đích khác trong thành phần của mình, vì vậy nó không chỉ dành cho điều đó. Tôi không có thời gian để xác nhận mặc dù.
moi_meme

Điều này sẽ không hoạt động nếu bạn muốn duy trì các thông số truy vấn, chẳng hạn như quảng cáo hoặc thông số theo dõi của google
Jon Tinsman

5

Tôi đã kết hợp urlTreevớilocation.go

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

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

Không chắc liệu toStringcó thể gây ra sự cố hay không, nhưng thật không may location.go, dường như là dựa trên chuỗi.


4

Nếu bạn muốn thay đổi các tham số truy vấn mà không thay đổi lộ trình. xem ví dụ dưới đây có thể giúp bạn: tuyến đường hiện tại là: / tìm kiếm & Tuyến đường mục tiêu là (không tải lại trang): / search? query = love

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

xin lưu ý: bạn có thể sử dụng this.router.navigate (['search'] thay vì this.router.navigate (['.']


Tôi không chắc rằng [.] Là một cách tiếp cận tốt hơn relativeTo:, nhưng .then()hữu ích - không biết rằng điều hướng () đã trả lại một lời hứa, rất vui vì bạn đã đăng!
Drenai

0

Đầu tiên, chúng ta cần nhập mô-đun bộ định tuyến từ bộ định tuyến góc và khai báo tên bí danh của nó

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

1. Bạn có thể thay đổi các tham số truy vấn bằng cách sử dụng hàm "router.navigate" và chuyển các tham số truy vấn

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

Nó sẽ cập nhật các tham số truy vấn trong lộ trình hiện tại tức là đã kích hoạt

  1. Bên dưới sẽ chuyển hướng đến trang abc với _id, ngày và tên dưới dạng tham số truy vấn

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

    Nó sẽ cập nhật các tham số truy vấn trong tuyến "abc" cùng với ba tham số truy vấn

Để tìm nạp các tham số truy vấn: -

    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
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.