web-dev-qa-db-fra.com

Angular 4.3 - Paramètres paramétrés HttpClient

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

Pourquoi ça ne marche pas? Il ne définit que le 'aaa' et PAS le 'bbb'

De plus, j'ai un objet {aaa: 111, bbb: 222} Comment puis-je définir toutes les valeurs sans boucle?

UPDATE (cela semble fonctionner, mais comment éviter la boucle?)

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

Avant la version 5.0.0-beta.6

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

Depuis la version 5.0.0-beta.6

Depuis la version 5.0.0-beta.6 (2017-09-03), ils ont ajouté une nouvelle fonctionnalité (accepte la mappe d'objets pour les en-têtes et paramètres HttpClient).

À l'avenir, l'objet peut être passé directement à la place de 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})
}
66
Michalis

HttpParams se veut immuable. Les méthodes set et append ne modifient pas l'instance existante. Au lieu de cela, ils renvoient de nouvelles instances, avec les modifications appliquées.

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

Cette approche fonctionne bien avec la méthode de chaînage:

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

... bien que cela puisse être gênant si vous devez en emballer un dans des conditions.

Votre boucle fonctionne parce que vous récupérez une référence à la nouvelle instance renvoyée. Le code que vous avez posté qui ne fonctionne pas ne fonctionne pas. Il appelle simplement set () mais ne récupère pas le résultat.

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

Dans les versions plus récentes de @angular/common/http (versions 5.0 et supérieures, par son apparence), vous pouvez utiliser la clé fromObject de HttpParamsOptions pour passer l'objet directement dans:

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

Cela lance juste une boucle forEachsous le capot , bien que:

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

Pour moi, enchaîner set méthodes est le moyen le plus propre

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

Couple d'alternatives faciles

Sans utiliser les objets HttpParams

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

this.http.post(url, body);

Utiliser HttpParams Objets

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

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

Une autre option est la suivante:

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

Comme la classe HTTP Params est immuable, vous devez donc chaîner la méthode set:

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

En utilisant cela, vous pouvez éviter la boucle.

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

De plus, je suggère de faire toHttpParams une fonction dans votre service couramment utilisé. Vous pouvez donc appeler la fonction pour convertir l'objet en 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());
}

Mise à jour:

Depuis la version 5.0.0-beta.6 (2017-09-03), ils ont ajouté une nouvelle fonctionnalité ( accepte la carte des objets pour les en-têtes et les paramètres HttpClient )

À l'avenir, l'objet peut être passé directement à la place de HttpParams.

C’est l’autre raison si vous avez utilisé une fonction commune telle que toHttpParams mentionnée ci-dessus, vous pouvez facilement la supprimer ou effectuer des modifications si nécessaire.

5
Lahar Shah

Pour autant que je puisse voir de la mise en œuvre à https://github.com/angular/angular/blob/master/packages/common/http/src/params.ts

Vous devez fournir des valeurs séparément - Vous ne pouvez pas éviter votre boucle.

Il existe également un constructeur qui prend une chaîne en tant que paramètre, mais sous la forme param=value&param2=value2, il n'y a donc pas d'accord pour vous (dans les deux cas, vous finirez par boucler votre objet).

Vous pouvez toujours signaler un problème/demande de fonctionnalité à angular, ce que je conseille vivement: https://github.com/angular/angular/issues

PS: Rappelez-vous de la différence entre les méthodes set et append;)

2
Maciej Treder

Puisque @MaciejTreder a confirmé la nécessité de la boucle, voici un wrapper qui vous permettra éventuellement d’ajouter à un ensemble de paramètres par défaut:

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

Vous pouvez l'utiliser comme ceci:

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

Ma classe d'assistance (ts) pour convertir n'importe quel objet dto complexe (pas seulement "dictionnaire de chaînes") en 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