Angular 4.3-HttpClient set params


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

3
私はあなたに同意しますhttpParams.set('bbb', '222');。私は最初にそれを試しましたが、非常に混乱していました。しかし、その行をhttpParams = httpParams.set('bbb','222');作品に置き換えてください。2を設定しているだけの人にとっては、以下の別のユーザーからの連鎖回答もいいでしょう。
アンジェラP

1
@AngelaPanが提案しているように、割り当て(=)を使用するだけで、ループを使用する必要はありません。可変および不変についても読んでください。
Junaid 2018

条件付きHttpParamsセット更新機能に投票してください:github.com/angular/angular/issues/26021
Serge

回答:


94

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

私は5.2.6を使用していますが、明示的にケースに入れない限り、paramsピースの辞書は使用されませんany。それは本当に意図された用途ですか?
ガーゴイル

6
@ Gargoyle- { params: <any>params }tsコンパイラの問題を回避するために、オブジェクトを任意の場所にキャストできます
Kieran

2
null型の文字列型のパラメータは「null」を返し、数値、ブール値、日付をサポートしません
OmarAMEZOUG19年

数値、ブール値、日付のサポートがない場合のバグレポートへのリンクは次のとおりです:github.com/angular/angular/issues/23856
angular

83

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

1
不変のHttpParamsの選択がいかに奇妙であるか、これはブロックポイントであり、受け入れられる答えであるはずです
Nicolas

45

最近のバージョン@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]);
});

なぜfromObjectと言っているのですか?任意のオブジェクトにすることができます。
クリスチャンマシュー

@ChristianMatthew HttpParamsのコンストラクターは、「任意のオブジェクト」を取得 できません。HttpParamsOptionsを取得します。つまり、任意のオブジェクトをパラメータとしてリクエストに渡すことができます。はい。ただし、v5からのみです。そうでなければ、私はあなたが何を求めているのかわかりません。
jonrsharpe

fromObjectという言葉<<それは何ですか
クリスチャンマシュー

@ChristianMatthewあなたが何を求めているのかわかりません。そのプロパティが何であるか知りたいですか?APIドキュメントを見ましたか?または答えの例?
jonrsharpe

1
@ChristianMatthewあなたが何を求めているのかわかりません。「APIバージョン」とはどういう意味ですか。Angularバージョン?回答で私がリンクしたコミットを確認できます。5.0で導入されたと明示的に述べました。また、今すぐマスターで確認することもできます:github.com/angular/angular/blob/master/packages/common/http/src/…。あなたがどんな問題を抱えているのか私にはわかりません。
jonrsharpe

21

私の場合、連鎖set方法が最もクリーンな方法です

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

3
HttpParamsはHttpHeadersのように不変です。つまり、この場合、2番目の.set()呼び出しは機能しません。これは、1回のヒットで設定する必要があります。または、OPが更新で提案したように、出力を新しい変数に割り当てる.append()メソッドを使用します。
WPalombini 2017

2
@WPalombiniマイクのチェーンセットを試しました。そしてそれは機能します!パラメータが2つしかない人にはいいと思います。理解しやすいです。
アンジェラP

19

簡単な選択肢のカップル

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

これは受け入れられた答えでなければなりません。シンプルでクリーン。
カルサス



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のような1つの一般的な関数を使用した場合、それを簡単に削除したり、必要に応じて変更したりできるもう1つの理由です。


こんにちは、正常に動作していますが、追加の未定義のキー値をparamとして追加します
AbhijitJagtap18年

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:setappendメソッドの違いを覚えておいてください;)


違いは何ですか?
クリスチャンマシュー

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

2

複雑なdtoオブジェクト(「文字列辞書」だけでなく)をHttpParamsに変換するためのヘルパークラス(ts):

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

あなたは本当にこれを必要としません、Angularparams.tsはそれ自身のエンコーディングを持っています。実装を確認します。github.com/angular/angular/blob/master/packages/common/http/src/...
Davideas

1

たとえば、同じキー名で複数のパラメータを追加する場合は、これを追加したかっただけです。www.test.com/ home?id = 1&id = 2

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

追加を使用します。setを使用すると、前の値が同じキー名で上書きされます。


0

このソリューションは私のために働いています、

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.