'Structure formData in an array

I have an extensive form and I'm trying to organize this so that it remains practicable for the plan that I intend to have with it.

An example showing what my form looks like:

<input type="text" name="data[0][name]">
<input type="email" name="data[0][email]">
<input type="tel" name="data[0][phone]">

<input type="text" name="data[1][name]">
<input type="email" name="data[1][email]">
<input type="tel" name="data[1][phone]">

I want this to return as:

 - data
    - data[0]
       - data[name]
       - data[email]
       - data[phone]
    - data[1]
       - data[name]
       - data[email]
       - data[phone]

But with new FormData(form); and then Object.fromEntries(formData) I'm just getting it on separate lines (as one large array).

Can someone help me with an easy way of converting these in a dynamic way because in my actual setup I have dozens of fields. So manually is not a desired option for me.

Thanks!



Solution 1:[1]

To convert a (single layer) NodeList of form elements into a nested object, using the form element name components, you can loop over the data form elements:

const dataform_obj = {} // instantiate empty object

// specify regular expression to capture name components
// for example: data[0][email]
const dataform_re = /^([^\[]+)(\[\d+\])(\[[^\]]+\])$/;

// convert form elements into array then loop
[...document.querySelector('#dataform').elements].forEach(function (elem) {

    // capture name components
    const match = elem.name.match(dataform_re);
    // match[1] is first name, match[2] is index, match[3] is last name
    // for example, ["data", "0", "email"]

  // instantiate sub-objects if do not exist
  if ( !dataform_obj[match[1]] ) { 
    dataform_obj[match[1]] = {}; 
  }
  if ( !dataform_obj[match[1]][match[1] + match[2]] ) { 
    dataform_obj[match[1]][match[1] + match[2]] = {}; 
  }

  // assign element value to object
  dataform_obj[match[1]][match[1] + match[2]][match[1] + match[3]] = elem.value;
})

Above, a javascript regular expression is used to capture the various components of the form element name. Those components are then used to build the object hierarchy.

console.log(dataform_obj);

...produces:

data: {
  data[0]: {
    data[email]: "",
    data[name]: "",
    data[phone]: ""
  },
  data[1]: {
    data[email]: "",
    data[name]: "",
    data[phone]: ""
  }

Online example: https://jsfiddle.net/n4m32wzh/


Perhaps, this is the format you're actually looking for:

data: {
  0: {
    email: "",
    name: "",
    phone: ""
  },
  1: {
    email: "",
    name: "",
    phone: ""
  }
}

Do that like this:

const dataform_obj = {};
const dataform_re = /^([^\[]+)\[(\d+)\]\[([^\]]+)\]$/;

[...document.querySelector('#dataform').elements].forEach(function (elem) {

  const match = elem.name.match(dataform_re)

  if ( !dataform_obj[match[1]] ) { 
    dataform_obj[match[1]] = {}; // <-- this level can alternatively be an array using [] instead of {} since the component is a number
  }
  if ( !dataform_obj[match[1]][match[2]] ) { 
    dataform_obj[match[1]][match[2]] = {}; 
  }

  dataform_obj[match[1]][match[2]][match[3]] = elem.value;
});
console.log(dataform_obj["data"])

Online example: https://jsfiddle.net/gnav6qb4/2/


If you already have a FormData Object, you can loop this way:

const dataform = new FormData(document.querySelector('#dataform'));
[...dataform.entries()].forEach(function (elem) {
  // elem is an array: [element name, element value]
  //...

Solution 2:[2]

I do not think there is a standard way to do this. You can try to find existing solution that turns FormData into JSON (https://www.google.com/search?q=formdata+to+json+npm), you can refer to solutions from How to convert FormData (HTML5 object) to JSON, or you can find inspiration e.g. in https://github.com/therealparmesh/object-to-formdata and write reverse operation. The complexity of your solution will depend on the complexity of your data and required performance for the solution.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 ?ukasz Szcze?niak