Search code examples
angulartypescriptangular-httpclientangular5

Angular 5 new immutable HttpClient breaks dynamic URL params


I have not worked too much with immutables in Typescript but the new Angular update has me stuck. I tried updating my own Http service with the new Http lib. Now I cannot dynamically add url parameters to Http GET requests.

The issue is explained here: https://medium.com/spektrakel-blog/angular-httpclient-enforces-immutability-dad161d8714b

I have a simple function that is supposed to handle different ways of dynamically adding, either by passing a generic object or an object with both a 'key' and a 'value' property. It looks like this:

public setParams(reqOptions) {
  let params;
  if (reqOptions) {
    if (reqOptions.key && reqOptions.value) {
      params = new URLSearchParams;
      params.append(reqOptions.key, reqOptions.value);
    } else {
      params = new URLSearchParams;
      for (let item in reqOptions) {
        if (reqOptions.hasOwnProperty(item)) {
          params.append(item, reqOptions[item]);
        }
      }
    }
  }
  return params;
}

Is there any way to recreate this functionality with immutables?

So if I had an object such as

{
  status: 'new',
  per_page: 50,
  page: 0
}

And I called the above function like this

listShipments(reqOptions?): Observable<any> {
  let params = this.setParams(reqOptions);
  return this.http.get(this.baseUrl + '/shipments', {params: params})
    .map(this.extractData);
}

it would rewrite the request url to

shipments?status=new&per_page=50&page=0

I found this overly useful as I could easily pass a dynamic set of parameters along with the call. How could I recreate this with immutables?

(btw: so much for "non-breaking", switching to immutables seems rather non-trivial to update in this case)


Solution

  • Because the HttpClient parameters, headers etc... are immutable, every time you try to modify, a brand new object is returned. This means that you must capture this new reference for your changes to persist. Your new function will look something like this:

    setParams(reqOptions:any){
      let params = new HttpParams();
      if(!reqOptions) return params;
    
      if(reqOptions.key && reqOptions.value){
        return params.set(reqOptions.key, reqOptions.value);
      }
    
      for(let key of Object.keys(reqOptions)){
        params = params.set(key,reqOptions[key]);
      }
      return params;
    }