Angular 4.3 - HttpClient 设置参数
Angular 4.3 - HttpClient set params
let httpParams = new HttpParams().set('aaa', '111');
httpParams.set('bbb', '222');
为什么这不起作用?
它只设置 'aaa' 而不是 'bbb'
此外,我有一个对象 { aaa: 111, bbb: 222 }
如何在不循环的情况下设置所有值?
UPDATE(这似乎可行,但如何避免循环?)
let httpParams = new HttpParams();
Object.keys(data).forEach(function (key) {
httpParams = httpParams.append(key, data[key]);
});
就我在 https://github.com/angular/angular/blob/master/packages/common/http/src/params.ts
的实施情况而言
您必须单独提供值 - 您无法避免循环。
还有一个将字符串作为参数的构造函数,但它的形式是 param=value¶m2=value2
,所以对您来说没有任何意义(在这两种情况下,您都将循环对象)。
您可以随时向 angular 报告 issue/feature 请求,我强烈建议:
https://github.com/angular/angular/issues
PS:记住 set
和 append
方法之间的区别 ;)
对我来说,链接 set
方法是最干净的方法
const params = new HttpParams()
.set('aaa', '111')
.set('bbb', "222");
HttpParams 是不可变的。 set
和 append
方法不会修改现有实例。相反,他们 return 新实例,应用了更改。
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');
...尽管如果您需要将它们中的任何一个包装在条件中,这可能会很尴尬。
您的循环有效,因为您正在获取对 returned 新实例的引用。您发布的代码不起作用,不起作用。它只是调用 set() 但不获取结果。
let httpParams = new HttpParams().set('aaa', '111'); // now it has aaa
httpParams.set('bbb', '222'); // result has both but is discarded
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 开始
Since 5.0.0-beta.6 (2017-09-03) they added new feature (accept object map for HttpClient headers & params)
Going forward the object can be passed directly instead of 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})
}
由于@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
另一种方法是:
this.httpClient.get('path', {
params: Object.entries(data).reduce((params, [key, value]) => params.set(key, value), new HttpParams());
});
使用这个你可以避免循环。
// 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());
}
更新:
Since 5.0.0-beta.6 (2017-09-03) they added new feature (accept
object map for HttpClient headers & params)
Going forward the object can be passed directly instead of HttpParams.
这是另一个原因,如果您使用了一个常用函数,如上面提到的 toHttpParams,您可以轻松删除它或根据需要进行更改。
在 @angular/common/http
的更新版本中(5.0 及更高版本,从外观上看),您可以使用 HttpParamsOptions
的 fromObject
键直接传递对象:
let httpParams = new HttpParams({ fromObject: { aaa: 111, bbb: 222 } });
这只是运行一个 forEach
循环 under the hood,不过:
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]);
});
由于 HTTP 参数 class 是不可变的,因此您需要将
设置方法:
const params = new HttpParams()
.set('aaa', '111')
.set('bbb', "222");
几个简单的选择
不使用 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);
这个解决方案对我有用,
let params = new HttpParams();
Object.keys(data).forEach(p => {
params = params.append(p.toString(), data[p].toString());
});
我的助手 class (ts) 将任何复杂的 dto 对象(不仅 "string dictionary")转换为 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
只是想补充一点,如果你想添加多个具有相同键名的参数,例如:
www.test.com/home?id=1&id=2
let params = new HttpParams();
params = params.append(key, value);
使用append,如果使用set,会覆盖之前相同键名的值
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 });
}
使用 set()
来自Angular Official Documentation of set()
set(param: string, value: string | number | boolean): HttpParams
Returns HttpParams: A new body with the new value.
现在,让我们看看如何添加一些参数 -
const params = new HttpParams()
.set('aaa', '111')
.set('bbb', "222");
请注意,我们正在通过链接 set() 方法来构造 HTTPParams 对象。原因是 HTTPParams 是不可变的.
每次调用 set 方法都会 return 一个具有新值的新 HttpParams 对象。我们需要先获取 returned HttpParams 对象,然后使用它进行进一步修改。
因此,如果我们执行以下操作,它将不起作用
const params = new HttpParams(); // empty HttpParams object
params.set('aaa', '111'); // lost
params.set('bbb', "222"); // lost
我们只调用 set
但不保留 returned 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'
});
let httpParams = new HttpParams().set('aaa', '111');
httpParams.set('bbb', '222');
为什么这不起作用? 它只设置 'aaa' 而不是 'bbb'
此外,我有一个对象 { aaa: 111, bbb: 222 } 如何在不循环的情况下设置所有值?
UPDATE(这似乎可行,但如何避免循环?)
let httpParams = new HttpParams();
Object.keys(data).forEach(function (key) {
httpParams = httpParams.append(key, data[key]);
});
就我在 https://github.com/angular/angular/blob/master/packages/common/http/src/params.ts
的实施情况而言您必须单独提供值 - 您无法避免循环。
还有一个将字符串作为参数的构造函数,但它的形式是 param=value¶m2=value2
,所以对您来说没有任何意义(在这两种情况下,您都将循环对象)。
您可以随时向 angular 报告 issue/feature 请求,我强烈建议: https://github.com/angular/angular/issues
PS:记住 set
和 append
方法之间的区别 ;)
对我来说,链接 set
方法是最干净的方法
const params = new HttpParams()
.set('aaa', '111')
.set('bbb', "222");
HttpParams 是不可变的。 set
和 append
方法不会修改现有实例。相反,他们 return 新实例,应用了更改。
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');
...尽管如果您需要将它们中的任何一个包装在条件中,这可能会很尴尬。
您的循环有效,因为您正在获取对 returned 新实例的引用。您发布的代码不起作用,不起作用。它只是调用 set() 但不获取结果。
let httpParams = new HttpParams().set('aaa', '111'); // now it has aaa
httpParams.set('bbb', '222'); // result has both but is discarded
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 开始
Since 5.0.0-beta.6 (2017-09-03) they added new feature (accept object map for HttpClient headers & params)
Going forward the object can be passed directly instead of 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})
}
由于@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
另一种方法是:
this.httpClient.get('path', {
params: Object.entries(data).reduce((params, [key, value]) => params.set(key, value), new HttpParams());
});
使用这个你可以避免循环。
// 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());
}
更新:
Since 5.0.0-beta.6 (2017-09-03) they added new feature (accept object map for HttpClient headers & params)
Going forward the object can be passed directly instead of HttpParams.
这是另一个原因,如果您使用了一个常用函数,如上面提到的 toHttpParams,您可以轻松删除它或根据需要进行更改。
在 @angular/common/http
的更新版本中(5.0 及更高版本,从外观上看),您可以使用 HttpParamsOptions
的 fromObject
键直接传递对象:
let httpParams = new HttpParams({ fromObject: { aaa: 111, bbb: 222 } });
这只是运行一个 forEach
循环 under the hood,不过:
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]);
});
由于 HTTP 参数 class 是不可变的,因此您需要将 设置方法:
const params = new HttpParams()
.set('aaa', '111')
.set('bbb', "222");
几个简单的选择
不使用 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);
这个解决方案对我有用,
let params = new HttpParams();
Object.keys(data).forEach(p => {
params = params.append(p.toString(), data[p].toString());
});
我的助手 class (ts) 将任何复杂的 dto 对象(不仅 "string dictionary")转换为 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
只是想补充一点,如果你想添加多个具有相同键名的参数,例如: www.test.com/home?id=1&id=2
let params = new HttpParams();
params = params.append(key, value);
使用append,如果使用set,会覆盖之前相同键名的值
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 });
}
使用 set()
来自Angular Official Documentation of set()
set(param: string, value: string | number | boolean): HttpParams
Returns HttpParams: A new body with the new value.
现在,让我们看看如何添加一些参数 -
const params = new HttpParams()
.set('aaa', '111')
.set('bbb', "222");
请注意,我们正在通过链接 set() 方法来构造 HTTPParams 对象。原因是 HTTPParams 是不可变的.
每次调用 set 方法都会 return 一个具有新值的新 HttpParams 对象。我们需要先获取 returned HttpParams 对象,然后使用它进行进一步修改。
因此,如果我们执行以下操作,它将不起作用
const params = new HttpParams(); // empty HttpParams object
params.set('aaa', '111'); // lost
params.set('bbb', "222"); // lost
我们只调用 set
但不保留 returned 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'
});