web-dev-qa-db-de.com

Angular 4.3 - HttpClient set params

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

Warum funktioniert das nicht? Es wird nur das 'aaa' und NICHT das 'bbb' gesetzt

Außerdem habe ich ein Objekt {aaa: 111, bbb: 222}. Wie kann ich alle Werte festlegen, ohne eine Schleife auszuführen?

UPDATE (dies scheint zu funktionieren, aber wie kann die Schleife vermieden werden?)

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

Vor 5.0.0-beta.6

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

Seit 5.0.0-beta.6

Seit 5.0.0-beta.6 (2017-09-03) wurde eine neue Funktion hinzugefügt (Objektzuordnung für HttpClient-Header und -Params akzeptieren).

In Zukunft kann das Objekt direkt anstelle von HttpParams übergeben werden.

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

HttpParams soll unveränderlich sein. Die Methoden set und append ändern die vorhandene Instanz nicht. Stattdessen geben sie neue Instanzen mit den vorgenommenen Änderungen zurück.

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

Dieser Ansatz eignet sich gut für die Verkettung von Methoden:

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

... obwohl das vielleicht umständlich ist, wenn Sie einen von ihnen in Bedingungen einwickeln müssen.

Ihre Schleife funktioniert, weil Sie einen Verweis auf die zurückgegebene neue Instanz abrufen. Der Code, den Sie gepostet haben, funktioniert nicht. Es ruft nur set () auf, erfasst aber nicht das Ergebnis.

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

In neueren Versionen von @angular/common/http (Ab 5.0) können Sie den fromObject Schlüssel von HttpParamsOptions verwenden um das Objekt direkt einzugeben:

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

Dies führt jedoch nur eine forEach -Schleife unter der Haube aus:

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

Für mich ist die Verkettung von set Methoden der sauberste Weg

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

Ein paar einfache Alternativen

Ohne HttpParams Objekte

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

this.http.post(url, body);

HttpParams Objekte verwenden

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

this.http.post(url, body);
11
Debojyoti

Eine andere Möglichkeit ist:

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

Da die HTTP-Params-Klasse unveränderlich ist, müssen Sie die set-Methode verketten:

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

Hiermit können Sie die Schleife umgehen.

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

Außerdem empfehle ich, toHttpParams in Ihrem häufig verwendeten Dienst zu verwenden. Sie können also die Funktion aufrufen, um das Objekt in die HttpParams umzuwandeln.

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

Update:

Seit 5.0.0-beta.6 (2017-09-03) wurde eine neue Funktion hinzugefügt ( Objektzuordnung für HttpClient-Header und -Params akzeptieren )

In Zukunft kann das Objekt direkt anstelle von HttpParams übergeben werden.

Dies ist der andere Grund, warum Sie eine häufig verwendete Funktion wie toHttpParams verwendet haben. Sie können diese einfach entfernen oder bei Bedarf Änderungen vornehmen.

5
Lahar Shah

Soweit ich aus der Implementierung sehen kann, unter https://github.com/angular/angular/blob/master/packages/common/http/src/params.ts

Sie müssen Werte separat angeben - Sie können Ihre Schleife nicht umgehen.

Es gibt auch einen Konstruktor, der einen String als Parameter akzeptiert, aber in der Form param=value&param2=value2 es gibt also kein Geschäft für Sie (in beiden Fällen beenden Sie die Schleife Ihres Objekts).

Sie können ein Problem/eine Funktionsanforderung jederzeit an winklig melden, was ich dringend rate: https://github.com/angular/angular/issues

PS: Denken Sie an den Unterschied zwischen den Methoden set und append.

2
Maciej Treder

Da @MaciejTreder bestätigt hat, dass eine Schleife ausgeführt werden muss, finden Sie hier einen Wrapper, mit dem Sie optional eine Reihe von Standardparametern hinzufügen können:

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

Du kannst es so benutzen:

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

Meine Helfer-Klasse (ts) zum Konvertieren komplexer dto-Objekte (nicht nur "String Dictionary") in 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
0
iliakolesnikov