Checkout my CSS Grid By Example and Getting Started With React video courses on Skillshare. Sign up now and get one free month of Skillshare.

FormData append array example not working in Javascript – and how to fix it

See an example of how to fix the common problems for appending arrays to FormData in Javascript.

While working on the example with the FormData API and the fetch() function I've encountered some less intuitive things and thought may be a good idea to share them.

Javascript FormData append array example

Let's take the below form example:

<form>
    <label for="user">šŸ§‘ā€ User: </label>
    <input type="text" name="user" id="user" value="john_doe">
    <br/>
    <label for="password">šŸ”’ Pass:</label>
    <input type="password" name="pass" id="pass" value="abcdef">
</form>

And a separate external button that will submit this form:

<button onclick="processForm()">
    Append array and serialize
</button>

form preview that we will use for FormData

As a final outcome when pressing the button we want to:

  • append an array with some extra flag values to the original form data (the username and password)
  • serialize the data form and send it to an API

Appending the data seems quite easy. We have a builtin append() method we can use:

function processForm() {
  const form = document.querySelector('form')
  let data = new FormData(form)
  const arr = ['1', '2', '3', '4']
  for (var i = 0; i < arr.length; i++) {
    data.append('arr[]', arr[i])
  }
}

However, here things started to get a bit weird.

Javascript FormData append array not working for console log

First I've tried to just console log the data object, to be sure that the array was added correctly:

function processForm() {
  // create the form data and append the array to it

  // ā›”ļø this will not work
  console.log(data)
  // šŸ‘ do this instead
  for (const pair of data.entries()) {
    console.log(`${pair[0]}, ${pair[1]}`);
  }
}

I just got an empty object back:

// [object FormData]
{}

After some extra research discovered that to correctly print the content of the form data we need to use the entries() method:

function processForm() {
  // create the form data and append the array to it

  // šŸ‘ do this instead
  for (const pair of data.entries()) {
    console.log(`${pair[0]}, ${pair[1]}`);
  }
}

Or we can directly use array destructuring:

for (const [key, value] of data.entries()) {
    console.log(`${key}, ${value}`)
}

The above code will print out the form data as expected, with the user
pass and arr[] fields.

Serializing FormData with append array not working

Having the printing sorted out, the next step was to serialize the data so that it can be sent in a request.

My initial plan was to use the Object.fromEntries() for serialization. So, here we go:

function processForm() {
  // create the form data and append the array to it

  // ā›”ļø this will not work
  const serialized = Object.fromEntries(data.entries());
  console.log(serialized)
}

However, if we take a look at the serialized object, we will see that for the arr[] filed only the last item from it was added in the serialization:

{user: 'john_doe', pass: 'abcdef', arr[]: '4'}

This is because if your form has multiple fields added with the same key, only the value of the last field with that name will be taken into account.

In order to serialize multiple fields with the same name we will need to check if the key already exists in serialized object and if so append to it:

function serializeForm(fData) {
  let s = {}
  for (let [key, value] of fData) {
      if (s[key] !== undefined) {
          if (!Array.isArray(s[key])) {
              s[key] = [s[key]]
          }
          s[key].push(value)
      } else {
          s[key] = value
      }
  }
  return s
}

function processForm() {
  // create the form data and append the array to it

  // šŸ‘ do this instead
  const serialized = serializeForm(data)
  console.log(serialized)
}

Now, if we log the object we will get the full array:

arr[]: (4) ['1', '2', '3', '4']
pass: "abcdef"
user: "john_doe"

Finally, once the serialization is done, we can use the JSON.stringify() method to wrap it for a request:

const requestData = JSON.stringify(serialized)

You can check out here the full codepen of this example.

Home Screencasts Best of Newsletter Search X