Angular 4.3 - HttpClient set params

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

Why this doesn't work? It only set the 'aaa' and NOT the 'bbb'

Also, I have an object { aaa: 111, bbb: 222 } How can I set all the values without looping?

UPDATE (this seems to work, but how can avoid the loop?)

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

Solution 1:

Before 5.0.0-beta.6

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

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

Solution 2:

HttpParams is intended to be immutable. The set and append methods don't modify the existing instance. Instead they return new instances, with the changes applied.

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

This approach works well with method chaining:

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

...though that might be awkward if you need to wrap any of them in conditions.

Your loop works because you're grabbing a reference to the returned new instance. The code you posted that doesn't work, doesn't. It just calls set() but doesn't grab the result.

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

Solution 3:

In more recent versions of @angular/common/http (5.0 and up, by the looks of it), you can use the fromObject key of HttpParamsOptions to pass the object straight in:

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

This just runs a forEach loop under the hood, though:

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

Solution 4:

Couple of Easy Alternatives

Without using HttpParams Objects

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

this.http.post(url, body);

Using HttpParams Objects

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

this.http.post(url, body);