Angular 4.3 - HttpClient mengatur params

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

Mengapa ini tidak berhasil? Ini hanya mengatur 'aaa' dan BUKAN 'bbb'

Juga, saya punya objek {aaa: 111, bbb: 222} Bagaimana saya bisa mengatur semua nilai tanpa perulangan?

PEMBARUAN (ini sepertinya berhasil, tetapi bagaimana cara menghindari loop?)

let httpParams = new HttpParams();
Object.keys(data).forEach(function (key) {
     httpParams = httpParams.append(key, data[key]);
});
Michalis
sumber
3
Saya setuju dengan Anda yang httpParams.set('bbb', '222');seharusnya berhasil. Saya mencoba yang pertama dan sangat bingung. Tapi gantilah baris itu dengan httpParams = httpParams.set('bbb','222');karya. bagi mereka yang hanya menyetel 2, rangkaian jawaban dari Pengguna lain di bawah ini juga bagus.
Angela P
1
cukup gunakan assignment (=) seperti yang disarankan @AngelaPan dan Anda tidak perlu menggunakan loop. Baca juga tentang yang bisa berubah dan tidak bisa diubah.
Junaid
silakan pilih fitur pembaruan set HttpParams bersyarat: github.com/angular/angular/issues/26021
Serge

Jawaban:

94

Sebelum 5.0.0-beta.6

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

Sejak 5.0.0-beta.6

Sejak 5.0.0-beta.6 (2017-09-03) mereka menambahkan fitur baru (menerima peta objek untuk header & param HttpClient)

Ke depannya, objek bisa diteruskan secara langsung sebagai ganti 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})
}
Michalis
sumber
Saya menggunakan 5.2.6 dan itu pasti tidak akan membutuhkan kamus untuk bagian params kecuali saya secara eksplisit memasukkannya any. Apakah itu benar-benar tujuan penggunaan?
Gargoyle
6
@Gargoyle - Anda bisa mentransmisikan objek Anda ke mana saja { params: <any>params }untuk menghindari masalah compiler ts
Kieran
2
Param dari tipe string yang null akan mengembalikan "null" dan Tidak Mendukung Nomor, Boolean dan Tanggal
Omar AMEZOUG
Berikut ini tautan ke laporan bug karena kurangnya dukungan Nomor, Boolean, dan Tanggal: github.com/angular/angular/issues/23856
EpicVoyage
83

HttpParams dimaksudkan agar tidak berubah. Metode setdan appendtidak mengubah instance yang ada. Sebaliknya, mereka mengembalikan instance baru, dengan perubahan yang diterapkan.

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

Pendekatan ini bekerja dengan baik dengan rangkaian metode:

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

... meskipun itu mungkin canggung jika Anda perlu membungkusnya dalam kondisi tertentu.

Loop Anda berfungsi karena Anda mengambil referensi ke instance baru yang dikembalikan. Kode yang Anda posting itu tidak berfungsi, tidak berfungsi. Itu hanya memanggil set () tetapi tidak mengambil hasilnya.

let httpParams = new HttpParams().set('aaa', '111'); // now it has aaa
httpParams.set('bbb', '222');                        // result has both but is discarded
Kaya
sumber
1
Betapa anehnya pilihan HttpParams yang tidak dapat diubah, ini adalah titik pemblokiran dan seharusnya menjadi jawaban yang diterima
Nicolas
45

Di versi yang lebih baru @angular/common/http(5.0 dan yang lebih baru, menurut tampilannya), Anda dapat menggunakan fromObjectkunci dari HttpParamsOptionsuntuk meneruskan objek secara langsung:

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

Ini hanya menjalankan satu forEachlingkaran di bawah tenda , meskipun:

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]);
});
jonrsharpe
sumber
mengapa kamu mengatakan fromObject? Itu bisa berupa objek apa saja.
Christian Matthew
@ChristianMatthew, konstruktor HttpParams tidak dapat mengambil "objek apapun", ia membutuhkan HttpParamsOptions. Jika maksud Anda, Anda dapat meneruskan objek apa pun sebagai params ke permintaan: ya, tetapi hanya dari v5. Kalau tidak, saya tidak yakin apa yang Anda tanyakan.
jonrsharpe
kata fromObject << apa itu benar
Christian Matthew
@Christian Saya tidak tahu apa yang Anda tanyakan. Ingin tahu apa properti itu? Apakah Anda melihat dokumen API? Atau contoh jawaban?
jonrsharpe
1
@Christian Saya tidak tahu apa yang Anda tanyakan. Apa yang Anda maksud dengan "versi API". Versi sudut ? Anda dapat melihat komit mana yang saya tautkan dalam jawaban dan saya katakan secara eksplisit itu diperkenalkan pada 5.0. Anda juga dapat membuka dan melihatnya di master sekarang: github.com/angular/angular/blob/master/packages/common/http/src/… . Tidak jelas bagi saya masalah apa yang Anda hadapi .
jonrsharpe
21

Bagi saya, setmetode rantai adalah cara terbersih

const params = new HttpParams()
.set('aaa', '111')
.set('bbb', "222");
Mike Kovetsky
sumber
3
HttpParams tidak dapat diubah seperti HttpHeaders, yang berarti bahwa panggilan .set () kedua tidak akan berfungsi dalam kasus ini. Itu perlu disetel dalam satu klik atau pergi dengan metode .append () menugaskan output ke variabel baru seperti yang disarankan OP pada pembaruannya.
WPalombini
2
@WPalini Saya baru saja mencoba rangkaian rantai Mike. dan itu berhasil! Menurut saya bagus untuk orang yang hanya memiliki 2 parameter. Mudah dimengerti.
Angela P
19

Beberapa Alternatif Mudah

Tanpa menggunakan HttpParamsObjek

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

this.http.post(url, body);

Menggunakan HttpParamsObjek

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

this.http.post(url, body);
Debojyoti
sumber
Ini harus menjadi jawaban yang diterima. Sederhana dan bersih.
Karsus
14

Opsi lain untuk melakukannya adalah:

this.httpClient.get('path', {
    params: Object.entries(data).reduce(
    (params, [key, value]) => params.set(key, value), new HttpParams());
});
Leibale Eidelman
sumber
Anda dapat menambahkan polyfill ( stackoverflow.com/questions/42410029/… )
Leibale Eidelman
harus mencoba sihir ini
Christian Matthew
9

Karena kelas HTTP Params tidak dapat diubah, maka Anda perlu merangkai metode yang ditetapkan:

const params = new HttpParams()
.set('aaa', '111')
.set('bbb', "222");
Adnan Abdul Khaliq
sumber
7

Dengan menggunakan ini, Anda dapat menghindari pengulangan.

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

Selanjutnya, saya sarankan membuat fungsi toHttpParams di layanan yang biasa Anda gunakan. Jadi Anda bisa memanggil fungsi untuk mengonversi objek ke 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());
}

Memperbarui:

Sejak 5.0.0-beta.6 (2017-09-03) mereka menambahkan fitur baru ( menerima peta objek untuk header & param HttpClient )

Ke depannya, objek bisa diteruskan secara langsung sebagai ganti HttpParams.

Ini adalah alasan lain jika Anda telah menggunakan satu fungsi umum seperti toHttpParams yang disebutkan di atas, Anda dapat dengan mudah menghapusnya atau melakukan perubahan jika diperlukan.

Lahar Shah
sumber
Hai berfungsi dengan baik tetapi tambahkan nilai kunci ekstra yang tidak ditentukan sebagai parameter
Abhijit Jagtap
3

Sejauh yang saya lihat dari implementasinya di https://github.com/angular/angular/blob/master/packages/common/http/src/params.ts

Anda harus memberikan nilai secara terpisah - Anda tidak dapat menghindari loop Anda.

Ada juga konstruktor yang mengambil string sebagai parameter, tetapi dalam bentuk param=value&param2=value2sehingga tidak ada kesepakatan untuk Anda (dalam kedua kasus Anda akan menyelesaikan perulangan objek Anda).

Anda selalu dapat melaporkan masalah / permintaan fitur ke sudut, yang sangat saya sarankan: https://github.com/angular/angular/issues

PS: Ingat tentang perbedaan antara setdan appendmetode;)

Maciej Treder
sumber
apa perbedaannya?
Christian Matthew
2

Karena @MaciejTreder mengonfirmasi bahwa kita harus melakukan loop, berikut adalah pembungkus yang secara opsional memungkinkan Anda menambahkan ke satu set parameter default:

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

Anda dapat menggunakannya seperti ini:

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
James Irwin
sumber
2

Kelas pembantu saya (ts) untuk mengonversi objek dto yang kompleks (tidak hanya "kamus string") menjadi 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
iliakolesnikov
sumber
Anda benar-benar tidak membutuhkan ini, Angular params.tsmemiliki pengkodeannya sendiri. Periksa implementasinya: github.com/angular/angular/blob/master/packages/common/http/src/…
Davideas
1

Hanya ingin menambahkan itu jika Anda ingin menambahkan beberapa parameter dengan nama kunci yang sama misalnya: www.test.com/home?id=1&id=2

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

Gunakan append, jika Anda menggunakan set, itu akan menimpa nilai sebelumnya dengan nama kunci yang sama.

Luigi Cordoba Granera
sumber
0

Solusi ini bekerja untuk saya,

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

Rotceh
sumber