'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 |
