Home > other >  Structure formData in an array
Structure formData in an array

Time:05-14

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!

CodePudding user response:

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.

CodePudding user response:

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 can alternatively be an array using [] instead of {}
  }
  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/

  • Related