Angular 4.3 - HttpClient set params


94
let httpParams = new HttpParams().set('aaa', '111');
httpParams.set('bbb', '222');

Tại sao điều này không hoạt động? Nó chỉ đặt 'aaa' chứ KHÔNG phải 'bbb'

Ngoài ra, tôi có một đối tượng {aaa: 111, bbb: 222} Làm cách nào để đặt tất cả các giá trị mà không lặp lại?

CẬP NHẬT (điều này có vẻ hiệu quả, nhưng làm cách nào để tránh vòng lặp?)

let httpParams = new HttpParams();
Object.keys(data).forEach(function (key) {
     httpParams = httpParams.append(key, data[key]);
});

3
Tôi đồng ý với bạn rằng httpParams.set('bbb', '222');nên làm việc. Tôi đã thử điều đó đầu tiên và rất bối rối. Nhưng hãy thay thế dòng đó bằng httpParams = httpParams.set('bbb','222');các tác phẩm. đối với những người chỉ thiết lập 2, câu trả lời chuỗi từ Người dùng khác bên dưới cũng rất hay.
Angela P

1
chỉ cần sử dụng gán (=) như @AngelaPan đã đề xuất và bạn không cần phải sử dụng vòng lặp. Cũng đọc về có thể thay đổi và bất biến.
Junaid

vui lòng bỏ phiếu cho tính năng cập nhật bộ HttpParams có điều kiện: github.com/angular/angular/issues/26021
Serge

Câu trả lời:


94

Trước 5.0.0-beta.6

let httpParams = new HttpParams();
Object.keys(data).forEach(function (key) {
     httpParams = httpParams.append(key, data[key]);
});

Kể từ 5.0.0-beta.6

Kể từ phiên bản 5.0.0-beta.6 (2017-09-03), họ đã thêm tính năng mới (chấp nhận bản đồ đối tượng cho tiêu đề và thông số HttpClient)

Về phía trước, đối tượng có thể được truyền trực tiếp thay vì HttpParams.

getCountries(data: any) {
    // We don't need any more these lines
    // let httpParams = new HttpParams();
    // Object.keys(data).forEach(function (key) {
    //     httpParams = httpParams.append(key, data[key]);
    // });

    return this.httpClient.get("/api/countries", {params: data})
}

Tôi đang sử dụng 5.2.6 và nó chắc chắn sẽ không lấy từ điển cho phần tham số trừ khi tôi viết rõ ràng cho nó any. Đó có thực sự là mục đích sử dụng?
Gargoyle

6
@Gargoyle - bạn chỉ có thể cast đối tượng của bạn cho bất kỳ { params: <any>params }để tránh các vấn đề biên dịch ts
Kieran

2
Các tham số của loại chuỗi là null sẽ trả về "null" và không hỗ trợ Số, Boolean và Ngày
Omar AMEZOUG 12/04/19

Dưới đây là một liên kết đến các báo cáo lỗi cho việc thiếu Number, Boolean và hỗ trợ ngày: github.com/angular/angular/issues/23856
EpicVoyage

83

HttpParams được thiết kế để không thay đổi. Các phương thức setappendkhông sửa đổi phiên bản hiện có. Thay vào đó, chúng trả về các phiên bản mới với các thay đổi được áp dụng.

let params = new HttpParams().set('aaa', 'A');    // now it has aaa
params = params.set('bbb', 'B');                  // now it has both

Cách tiếp cận này hoạt động tốt với chuỗi phương pháp:

const params = new HttpParams()
  .set('one', '1')
  .set('two', '2');

... mặc dù điều đó có thể hơi khó xử nếu bạn cần kết hợp bất kỳ điều kiện nào trong số chúng.

Vòng lặp của bạn hoạt động vì bạn đang lấy một tham chiếu đến phiên bản mới được trả về. Mã bạn đã đăng không hoạt động, không. Nó chỉ gọi set () nhưng không lấy kết quả.

let httpParams = new HttpParams().set('aaa', '111'); // now it has aaa
httpParams.set('bbb', '222');                        // result has both but is discarded

1
Thật kỳ lạ khi lựa chọn một HttpParams không thể thay đổi, đây là điểm chặn và phải là câu trả lời được chấp nhận
Nicolas

45

Trong các phiên bản gần đây hơn của @angular/common/http(5.0 trở lên, nhìn bề ngoài), bạn có thể sử dụng fromObjectphím của HttpParamsOptionsđể chuyển thẳng đối tượng vào:

let httpParams = new HttpParams({ fromObject: { aaa: 111, bbb: 222 } });

Tuy nhiên, điều này chỉ chạy một forEachvòng dưới mui xe :

this.map = new Map<string, string[]>();
Object.keys(options.fromObject).forEach(key => {
  const value = (options.fromObject as any)[key];
  this.map !.set(key, Array.isArray(value) ? value : [value]);
});

tại sao bạn lại nói từObject? Nó có thể là bất kỳ đối tượng nào.
Christian Matthew

@ChristianMatthew phương thức khởi tạo của HttpParams không thể lấy "bất kỳ đối tượng nào", nó phải lấy HttpParamsOptions. Nếu bạn có nghĩa là bạn có thể chuyển bất kỳ đối tượng nào dưới dạng tham số cho một yêu cầu: có, nhưng chỉ từ v5. Nếu không, tôi không chắc bạn đang hỏi gì.
jonrsharpe

từ fromObject << điều đó đúng là gì
Christian Matthew

@ChristianMatthew Tôi không biết bạn đang hỏi gì. Bạn có muốn biết tài sản đó là gì không? Bạn đã xem tài liệu API chưa? Hoặc ví dụ trong câu trả lời?
jonrsharpe

1
@ChristianMatthew Tôi không biết bạn đang hỏi gì. Ý bạn là "phiên bản API". Phiên bản Angular ? Bạn có thể thấy cam kết mà tôi đã liên kết trong câu trả lời và tôi đã nói rõ ràng rằng nó đã được giới thiệu trong 5.0. Bạn cũng có thể truy cập và xem nó trong chính ngay bây giờ: github.com/angular/angular/blob/master/packages/common/http/src/… . Tôi không rõ bạn gặp vấn đề gì .
jonrsharpe

21

Đối với tôi, setphương pháp chuỗi là cách sạch sẽ nhất

const params = new HttpParams()
.set('aaa', '111')
.set('bbb', "222");

3
HttpParams là bất biến giống như HttpHeaders, có nghĩa là lệnh gọi .set () thứ hai sẽ không hoạt động trong trường hợp này. Nó cần được đặt trong một lần truy cập hoặc đi với phương thức .append () gán đầu ra cho một biến mới như OP đã đề xuất trong bản cập nhật của anh ấy.
WPalombini

2
@WPalombini Tôi vừa thử bộ chuỗi của Mike. và nó hoạt động! Tôi nghĩ rằng nó tốt cho những người chỉ có 2 tham số. Rất dễ hiểu.
Angela P

19

Một vài lựa chọn thay thế dễ dàng

Không sử dụng HttpParamsđối tượng

let body = {
   params : {
    'email' : emailId,
    'password' : password
   }
}

this.http.post(url, body);

Sử dụng HttpParamscác đối tượng

let body = new HttpParams({
  fromObject : {
    'email' : emailId,
    'password' : password
  }
})

this.http.post(url, body);

Đây phải là câu trả lời được chấp nhận. Đơn giản và sạch sẽ.
Karsus


9

Vì lớp HTTP Params là không thay đổi, do đó bạn cần chuỗi phương thức thiết lập:

const params = new HttpParams()
.set('aaa', '111')
.set('bbb', "222");

7

Sử dụng điều này, bạn có thể tránh được vòng lặp.

// obj is the params object with key-value pair. 
// This is how you convert that to HttpParams and pass this to GET API. 

const params = Object.getOwnPropertyNames(obj)
               .reduce((p, key) => p.set(key, obj[key]), new HttpParams());

Hơn nữa, tôi khuyên bạn nên tạo chức năng toHttpParams trong dịch vụ thường được sử dụng của bạn. Vì vậy, bạn có thể gọi hàm để chuyển đổi đối tượng thành HttpParams .

/**
 * Convert Object to HttpParams
 * @param {Object} obj
 * @returns {HttpParams}
 */
toHttpParams(obj: Object): HttpParams {
    return Object.getOwnPropertyNames(obj)
        .reduce((p, key) => p.set(key, obj[key]), new HttpParams());
}

Cập nhật:

Kể từ phiên bản 5.0.0-beta.6 (2017-09-03), họ đã thêm tính năng mới ( chấp nhận bản đồ đối tượng cho tiêu đề và thông số HttpClient )

Về phía trước, đối tượng có thể được truyền trực tiếp thay vì HttpParams.

Đây là lý do khác nếu bạn đã sử dụng một chức năng phổ biến như toHttpParams đã đề cập ở trên, bạn có thể dễ dàng loại bỏ nó hoặc thực hiện thay đổi nếu cần.


Hi tốt của nó làm việc nhưng append thêm undefined giá trị quan trọng như param
Abhijit Jagtap

3

Theo như tôi có thể thấy từ việc triển khai tại https://github.com/angular/angular/blob/master/packages/common/http/src/params.ts

Bạn phải cung cấp các giá trị một cách riêng biệt - Bạn không thể tránh vòng lặp của mình.

Cũng có một phương thức khởi tạo nhận một chuỗi làm tham số, nhưng nó ở dạng param=value&param2=value2nên không có thỏa thuận nào cho Bạn (trong cả hai trường hợp, bạn sẽ kết thúc bằng việc lặp đối tượng của mình).

Bạn luôn có thể báo cáo vấn đề / yêu cầu tính năng đối với góc cạnh, điều tôi thực sự khuyên: https://github.com/angular/angular/issues

Tái bút: Hãy nhớ về sự khác biệt giữa setappendcác phương pháp;)


Sự khác biệt là gì?
Christian Matthew

2

Vì @MaciejTreder xác nhận rằng chúng tôi phải lặp lại, đây là trình bao bọc sẽ cho phép bạn thêm vào một tập hợp các tham số mặc định theo tùy chọn:

function genParams(params: object, httpParams = new HttpParams()): object {
    Object.keys(params)
        .filter(key => {
            let v = params[key];
            return (Array.isArray(v) || typeof v === 'string') ? 
                (v.length > 0) : 
                (v !== null && v !== undefined);
        })
        .forEach(key => {
            httpParams = httpParams.set(key, params[key]);
        });
    return { params: httpParams };
}

Bạn có thể sử dụng nó như vậy:

const OPTIONS = {
    headers: new HttpHeaders({
        'Content-Type': 'application/json'
    }),
    params: new HttpParams().set('verbose', 'true')
};
let opts = Object.assign({}, OPTIONS, genParams({ id: 1 }, OPTIONS.params));
this.http.get(BASE_URL, opts); // --> ...?verbose=true&id=1

2

Lớp trợ giúp của tôi (ts) để chuyển đổi bất kỳ đối tượng dto phức tạp nào (không chỉ "từ điển chuỗi") sang HttpParams:

import { HttpParams } from "@angular/common/http";

export class HttpHelper {
  static toHttpParams(obj: any): HttpParams {
    return this.addToHttpParams(new HttpParams(), obj, null);
  }

  private static addToHttpParams(params: HttpParams, obj: any, prefix: string): HttpParams {    
    for (const p in obj) {
      if (obj.hasOwnProperty(p)) {
        var k = p;
        if (prefix) {
          if (p.match(/^-{0,1}\d+$/)) {
            k = prefix + "[" + p + "]";
          } else {
            k = prefix + "." + p;
          }
        }        
        var v = obj[p];
        if (v !== null && typeof v === "object" && !(v instanceof Date)) {
          params = this.addToHttpParams(params, v, k);
        } else if (v !== undefined) {
          if (v instanceof Date) {
            params = params.set(k, (v as Date).toISOString()); //serialize date as you want
          }
          else {
            params = params.set(k, v);
          }

        }
      }
    }
    return params;
  }
}

console.info(
  HttpHelper.toHttpParams({
    id: 10,
    date: new Date(),
    states: [1, 3],
    child: {
      code: "111"
    }
  }).toString()
); // id=10&date=2019-08-02T13:19:09.014Z&states%5B0%5D=1&states%5B1%5D=3&child.code=111

Bạn thực sự không cần điều này, Angular params.tscó bảng mã riêng của nó. Kiểm tra việc triển khai: github.com/angular/angular/blob/master/packages/common/http/src/…
Davideas

1

Chỉ muốn thêm điều đó nếu bạn muốn thêm một số tham số có cùng tên khóa, ví dụ: www.test.com/home?id=1&id=2

let params = new HttpParams();
params = params.append(key, value);

Sử dụng append, nếu bạn sử dụng set, nó sẽ ghi đè lên giá trị trước đó với cùng tên khóa.


0

Giải pháp này phù hợp với tôi,

let params = new HttpParams(); Object.keys(data).forEach(p => { params = params.append(p.toString(), data[p].toString()); });

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.