'How could I mount an object through forEach?

I have a form with several text inputs and I need to get the name and value of the input to generate an object. I don't know if this would be possible, but so far this is my code:

function getData(){
 const test = document.querySelectorAll('input')
 test.forEach((item) => {
   console.log('item:', item.name + item.value)
   //example
    {
     item.name = item.value
     ....
    }
   //example
    
 })
}

My intention is that item.name is the object's key name and item.value is the value.



Solution 1:[1]

This will do:

function getData(){
 const test = document.querySelectorAll('input')
 const result = {}
 test.forEach((item) => {
   console.log('item:', item.name + item.value)
   result[item.name] = item.value    
 })
 return result
}

You could achieve the same result with (barely) less code using test.reduce()

function getData(){
 const test = document.querySelectorAll('input')
 return test.reduce((result, item) => {
   console.log('item:', item.name + item.value)
   result[item.name] = item.value
   return result 
 }, {})
}

Solution 2:[2]

You need create a new object add data to it from fromEach, then return it:

function getData(){
 const test = document.querySelectorAll('input');
 const returnObj = {};
 test.forEach((item) => {
   returnObj[item.name] = item.value;
 })
 return returnObj;
}

console.log(getData());
<input name="test1" value="blah1">
<input name="test2" value="blah2a">
<input name="test3" value="blah3b">
<input name="test4" value="blah4c">
<input name="test6" value="blah6">

Solution 3:[3]

You can turn your results into an Array by passing your query results into Array.from, then map() the array into a shape that Object.fromEntries() is looking for to achieve this result:

function getData(){
  const elements = document.querySelectorAll('input');
  return Object.fromEntries(
    Array.from(elements).map(
      el => ([el.name, el.value])
    )
  );
}

console.log(getData());
<input name="test1" value="blah1">
<input name="test2" value="blah2a">
<input name="test3" value="blah3b">
<input name="test4" value="blah4c">
<input name="test6" value="blah6">

Solution 4:[4]

Here's a non-naive solution that properly encodes a <form> elements -

  • <input>
  • <input type="checkbox"> - includes only checked elements
  • <input type="radio"> - includes only the checked element
  • <select> - includes only the selected element
  • <textarea>

Note all disabled inputs are ignored. Some corner cases like <input type="file"> and <select multiple> have not been taken into account -

function formData(f) {
  return Object.fromEntries(
    Array.from(f.elements)
      .filter(item => {
        switch (item.type) {
          case "checkbox": return item.checked
          default: return !item.disabled
        }
      })
      .map(item => [item.name, item.value])
  )
}

console.log(formData(document.forms.foo))
<form id="foo">
  <p>hello world</p>
  <input name="a" value="A" />
  <input name="b" value="B" disabled />
  <textarea name="c" value="C">Ctext</textarea>
  <select name="e">
    <option value="E1">E1</option>
    <option value="E2" selected>E2</option>
  </select>
  <input type="checkbox" name="f1" value="F1" checked />
  <input type="checkbox" name="f2" value="F2" />
  <input type="radio" name="g" value="G1" />
  <input type="radio" name="g" value="G2" />
  <input type="radio" name="g" value="G3" checked />
</form>
{
  "a": "A",
  "c": "Ctext",
  "e": "E2",
  "f1": "F1",
  "g": "G3"
}

Solution 5:[5]

Update

I misunderstood that OP objective is a single object instead of an array of objects. Example A covers a single object as a result, and Example B covers an array of objects as a result.


Use HTMLFormElement and HTMLFormControlsCollection interfaces to reference any and all form controls? and <form>s. In the example, the result will be an array of object literals that represent form controls that have a value assigned -- form controls without values are ignored.
?Form controls are: <button>, <fieldset>, <input> , <object>, <output>, <select>, and <textarea>

Details are commented in examples

Example A

// Reference the <form>
const form = document.forms.data;

/*
Reference all form controls within <form>. 
Form controls includes <input>, <select>, <textarea>, etc.
*/
const IO = form.elements;

/*
Pass in one or more DOM objects (as a NodeList, array, etc.)
*/
/**
 *  Run the DOM objects/nodes through .flatMap()
 *  Check each node...
 *    if it's a radio button... 
 *    AND it isn't checked...
 *    OR node doesn't have a .value...
 *    ...Return an empty array [] 
 *    (in .flatMap() returning an empty array results in
 *    nothing as if node was skipped.)
 */
/**
 *  Return an array of pairs (key/value) with key/values of:
 *   [[node.name, node.value]]
 *  The extra brackets is to ensure 
 *  output is an array of pairs, since
 *  since .flatMap() flattens one level
 *  of it's returned arrays.
 */
/**
 * Convert 2D array (pairs) into an     
 * object literal with Object.fromEntries()
 */
const getData = (nodes) => {
  const pairs = [...nodes].flatMap(node => {
    if (node.type === 'radio' && !node.checked || node.value === '') {
      return [];
    }
    return [
      [node.name, node.value]
    ];
  });
  return Object.fromEntries(pairs);
};
console.log(getData(IO));
.as-console-row::after { width: 0; font-size: 0; }
.as-console-row-code { width: 100%; word-break: break-word; }
.as-console-wrapper { max-height: 1.5em !important; max-width: 50%; min-height: 100%; margin-left: 50%; }
<form id='data'>
  <input name='A' value='Alpha'>
  <input name='B' value='Beta'>
  <input name='C' value='Gamma'>
  <input name='D' value='Delta'><br>
  <input name='rad' type='radio' value='1'>
  <input name='rad' type='radio' value='2'>
  <input name='rad' type='radio' value='3' checked>
  <input name='rad' type='radio' value='4'>
  <select id='sel' name='sel'>
    <option disabled></option>
    <option value='1'>I</option>
    <option value='2'>II</option>
    <option value='3'>III</option>
    <option selected value='4'>IV</option>
  </select>
  <textarea name='text'></textarea>
</form>

Example B

// Reference the <form>
const form = document.forms.data;

/*
Reference all form controls within <form>. 
Form controls includes <input>, <select>, <textarea>, etc.
*/
const IO = form.elements;

/*
Pass in one or more DOM objects (as a NodeList, array, etc.)
*/
/**
 *  Run the DOM objects/nodes through .flatMap()
 *  Check each node...
 *    if it's a radio button... 
 *    AND it isn't checked...
 *    OR node doesn't have a .value...
 *    ...Return an empty array [] 
 *    (in .flatMap() returning an empty array results in
 *    nothing as if node was skipped.)
 */
/**
 *  Return an object literal with key/values of:
 *   "name": node.name,
 *   "value": node.value
 */
const getData = (nodes) => {
  return [...nodes].flatMap(node => {
    if (node.type === 'radio' && !node.checked || node.value === '') {
      return [];
    }
    return Object.assign({}, {
      ['name']: node.name,
      ['value']: node.value
    })
  });
};
console.log(getData(IO));
.as-console-row::after { width: 0; font-size: 0; }
.as-console-row-code { width: 100%; word-break: break-word; }
.as-console-wrapper { max-height: 1.5em !important; max-width: 50%; min-height: 100%; margin-left: 50%; }
<form id='data'>
  <input name='A' value='Alpha'>
  <input name='B' value='Beta'>
  <input name='C' value='Gamma'>
  <input name='D' value='Delta'><br>
  <input name='rad' type='radio' value='1'>
  <input name='rad' type='radio' value='2'>
  <input name='rad' type='radio' value='3' checked>
  <input name='rad' type='radio' value='4'>
  <select id='sel' name='sel'>
    <option disabled></option>
    <option value='1'>I</option>
    <option value='2'>II</option>
    <option value='3'>III</option>
    <option selected value='4'>IV</option>
  </select>
  <textarea name='text'></textarea>
</form>

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 Pygy
Solution 2 vanowm
Solution 3
Solution 4
Solution 5