Search code examples
javascriptangularformshttp-post

How to convert Array of javascript objects to form-encoded for POST?


For an Angular(v14) application, I have a requirement to "POST the following form-encoded parameters to a given URL for a list of items where n is the zero based index of the lines"

Format:

 ItemNo[n]=<Item Identifier>
 Description[n]=<Item Identifier>

So, for example, 3 items would be like so:

 ItemNo[0]=1001
 Description[0]=a wonderful item
 ItemNo[1]=1002a
 Description[1]=something
 ItemNo[2]=1002c
 Description[2]=another thing

On my end, the items I need to POST in the form-encoded format are in an array like so:

 [
     { ItemNo: '1001', Description: 'a wonderful item' },
     { ItemNo: '1002a', Description: 'something' },
     { ItemNo: '1002c', Description: 'another thing' },
 ]

So I've been trying to figure out how to get the array of items into the correct format: Form-encoded, without much luck. Hoping someone can help!

I've found quite a few similar questions, (though I'm unsure if I am using the most appropriate search terms) but Angular evolves so quickly that each time I try to implement a suggestion, I find the suggested solution uses one or more depreciated methods, so I've ended up with quite a mess of failed attempts!

I've written a function which will rewrite my array to add the indexing to the keys, so now I've got:

 [
    { ItemNo[0]: '1001', Description[0]: 'a wonderful item' }
    { ItemNo[1]: '1002a', Description[1]: 'something' }
    { ItemNo[2]: '1002c', Description[2]: 'another thing' }
 ]

But how can I get this into a form-encoded type? Everything I have tried that seemed promising (most recently DefaultUrlSerializer()) seems to give me results like

 "/?0=%5Bobject%20Object%5D&1=%5Bobject%20Object%5D"

(not keyname=value)

Also, on my http.post() method, what should the incoming type be, to be posting "form-encoded"? I'm guessing string?

Solution Discarding my extra function to add the indexes to the keys, the final solution is:

 doFormParams(items: any[]): HttpParams {
  let params = new HttpParams();
  items.forEach((item, index) => {
    for(const key in item){
    params = params.append(`${key}[${index}]`,`${item[key]}`);
    }
  });
  return params;
}

Some users have pointed out that this would be easier to send as a JSON object. I agree, this would be my default. However the third party who has given me this requirement is well established and uses this same method to receive data from many sources, so I don't really expect them to modify their ways just to suit my preference! Once I knew the method I needed, the solution was simple enough.


Solution

  • Use HttpParams class https://angular.io/api/common/http/HttpParams:

    doFormParams(items: any[]): HttpParams {
      let params = new HttpParams();
      items.forEach((item, index) => {
        // do something
      });
      return params;
    }
    
    const headers = {
      'Content-Type': 'application/x-www-form-urlencoded'
    };
    
    this.http.post(url, params.toString(), { headers });