Angular 4.3 - HttpClient 设置参数

问题描述 投票:0回答:17
let httpParams = new HttpParams().set('aaa', '111');
httpParams.set('bbb', '222');

为什么这不起作用? 它只设置“aaa”而不是“bbb”

另外,我还有一个对象

{ aaa: 111, bbb: 222 }
如何在不循环的情况下设置所有值?

更新(这似乎可行,但如何避免循环?)

let httpParams = new HttpParams();
Object.keys(data).forEach(function (key) {
     httpParams = httpParams.append(key, data[key]);
});
angular angular-httpclient angular-http
17个回答
107
投票

HttpParams 旨在是不可变的。

set
append
方法不会修改现有实例。相反,它们返回应用了更改的新实例。

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

这种方法与方法链配合使用效果很好:

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

...尽管如果您需要将它们中的任何一个包裹在条件下,这可能会很尴尬。

您的循环之所以有效,是因为您正在获取对返回的新实例的引用。您发布的代码不起作用,不起作用。它只是调用 set() 但不获取结果。

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

107
投票

5.0.0-beta.6之前

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

自 5.0.0-beta.6 起

自 5.0.0-beta.6 (2017-09-03) 起,他们添加了新功能(接受 HttpClient 标头和参数的对象映射)

以后可以直接传递对象而不是 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})
}

57
投票

@angular/common/http
的最新版本(5.0 及更高版本,从外观上看),您可以使用
fromObject
HttpParamsOptions
键直接传递对象:

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

这只是在引擎盖下运行一个

forEach
循环,不过:

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

30
投票
几个简单的替代方案

不使用

HttpParams
对象

let body = { params : { 'email' : emailId, 'password' : password } } this.http.post(url, body);

使用

HttpParams
对象

let body = new HttpParams({ fromObject : { 'email' : emailId, 'password' : password } }) this.http.post(url, body);
    

23
投票
对于我来说,链接

set

 方法是最干净的方法

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

18
投票
另一种方法是:

this.httpClient.get('path', { params: Object.entries(data).reduce((params, [key, value]) => params.set(key, value), new HttpParams()); });
    

9
投票
由于 HTTP Params 类是不可变的,因此您需要链接 设置方法:

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

7
投票
使用这个可以避免循环。

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

此外,我建议在您常用的服务中制作

toHttpParams 函数。所以你可以调用该函数将对象转换为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()); }

更新:

自5.0.0-beta.6(2017-09-03)以来,他们添加了新功能(

接受 HttpClient 标头和参数的对象映射)

以后可以直接传递对象而不是 HttpParams。

这是另一个原因,如果您使用了像上面提到的

toHttpParams 这样的常用函数,您可以轻松删除它或根据需要进行更改。


3
投票
据我从

https://github.com/angular/angular/blob/master/packages/common/http/src/params.ts的实现中看到

您必须单独提供值 - 您无法避免循环。

还有一个构造函数,它接受一个字符串作为参数,但它的形式是

param=value&param2=value2

,所以对你来说没有什么好处(在这两种情况下,你都将循环你的对象来完成)。

您可以随时向 Angular 报告问题/功能请求,我强烈建议:

https://github.com/angular/angular/issues

PS:记住

set

append
 方法之间的区别;)


3
投票

appendAll 函数

import { HttpParams } from "@angular/common/http"; export class BuildUrl { /** * append all params * @param args {unknown[]} * @returns {HttpParams} */ static appendAll(...args: unknown[]): HttpParams { let params = new HttpParams(); args.forEach(param => { Object.keys(param).forEach((key) => { params = params.append(key, param[key]); }); }); return params; } }

我们如何在服务中使用它。

getData( pag: PaginationRequest, description: string = ''): Observable<any> { const params = BuildUrl.appendAll(pag, { description }, ); return this.http.get(url, { params }); }
    

2
投票
我的帮助器类(ts)将任何复杂的 dto 对象(不仅仅是“字符串字典”)转换为 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
    

2
投票
只是想添加一点,如果您想添加具有相同键名的多个参数,例如: www.test.com/home?id=1&id=2

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

使用append,如果使用set,则会覆盖之前同键名的值。


2
投票
既然 @MaciejTreder 确认我们必须循环,这里有一个包装器,可以选择让您添加到一组默认参数:

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 }; }
你可以像这样使用它:

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
    

1
投票
这个解决方案对我有用,

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


    


0
投票

使用set()

来自

Angular set() 官方文档

set(param: string, value: string | number | boolean): HttpParams


返回 HttpParams:具有新值的新主体。

现在,让我们看看如何添加一些参数 -

const params = new HttpParams() .set('aaa', '111') .set('bbb', "222");
请注意,我们通过链接 set() 方法来构造 HTTPParams 对象。原因是 

HTTPParams 是不可变的

每次调用 set 方法都会返回一个具有新值的新 HttpParams 对象。我们需要首先获取返回的 HttpParams 对象,然后使用它进行进一步修改。

所以,如果我们执行以下操作,它将

不起作用

const params = new HttpParams(); // empty HttpParams object params.set('aaa', '111'); // lost params.set('bbb', "222"); // lost
我们只调用 

set

 但不保留返回的 
HttpParams
 对象。因此,最后我们将得到一个空的 HttpParams 对象,并且对 set 的两次调用不会添加任何效果。为了使其发挥作用,我们需要执行以下操作 -
const params = new HttpParams(); // empty HttpParams object params = params.set('aaa', '111'); // storing the returned HttpParams object, now **it has aaa** params = params.set('bbb', "222"); // add another parameter and store it. so now **it has both aaa and bbb**

使用 fromString

您还可以使用 fromString 创建 httpParams。如果您已经准备好查询参数字符串,那就太好了。您可以使用以下语法来完成

const params = new HttpParams({ fromString: 'aaa=111&bbb=222' });



0
投票

此方法在 Angular 14 上运行良好。 使用

HttpParams

将参数传递给后端

get<T>(path: string): Observable<T> {
    let httpParams = new HttpParams();
    httpParams = httpParams.append("language", "en");
    httpParams = httpParams.append("pageNo", 1);
    httpParams = httpParams.append("pageSize", 10);

    const options = { params: httpParams };

    return this.http.get<T>(`${this.apiUrl}/${path}`, options);
}

// T is a generic type returned by the `get` method.

 getHttpParams(data: any) {
   let httpParams = new HttpParams();
   Object.keys(data).forEach(key => {
     if (data[key] != null) {
       if (typeof data[key] === "object") {
         var childData = data[key];
         Object.keys(childData).forEach(childKey => {
           httpParams = httpParams.append(childKey, childData[childKey]);
         });
       } else {
         httpParams = httpParams.append(key, data[key]);
       }
     }
   });
   return httpParams;
 }

0
投票

© www.soinside.com 2019 - 2024. All rights reserved.