Imagine I have an array of selected checkboxes. Each has a value and name that corresponds with a filter.
<input class="filter-item--checkbox" type="checkbox" name="colors" value="blue">
<input class="filter-item--checkbox" type="checkbox" name="colors" value="orange">
<input class="filter-item--checkbox" type="checkbox" name="items" value="chair">
<input class="filter-item--checkbox" type="checkbox" name="items" value="bed">
<input class="filter-item--checkbox" type="checkbox" name="material" value="plastic">
<input class="filter-item--checkbox" type="checkbox" name="material" value="wood">
How can I sort these into one array, like below?
const filters = [
'colors': [ 'blue', 'orange'],
'items': ['chair', 'bed'],
'material': ['plastic', 'wood'],
]
CodePudding user response:
You could get the elements and build an object of arrays.
const result = {};
for (const { name, value } of document.getElementsByClassName('filter-item--checkbox')) {
(result[name] ??= []).push(value);
}
console.log(result);
<input class="filter-item--checkbox" type="checkbox" name="colors" value="blue">
<input class="filter-item--checkbox" type="checkbox" name="colors" value="orange">
<input class="filter-item--checkbox" type="checkbox" name="items" value="chair">
<input class="filter-item--checkbox" type="checkbox" name="items" value="bed">
<input class="filter-item--checkbox" type="checkbox" name="material" value="plastic">
<input class="filter-item--checkbox" type="checkbox" name="material" value="wood">
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
For the OP's use case, where it was said that a solution should target just checked checkbox controls one could/should utilize the FormData
Web-API and its entries
method together with a reduce
task. Passing a form reference directly into the FormData
constructor ensures only active control data to be part of the form data object. Thus the name/key and value of an unchecked checkbox control gets not reflected by the form data object.
const formData = new FormData(document.forms[0]);
console.log(
Array
.from(
formData.entries()
)
.reduce((result, [key, value]) => {
const groupedValueList = (result[key] ??= []);
groupedValueList.push(value);
return result;
}, {})
);
.as-console-wrapper { min-height: 85%!important; }
<form>
<input type="checkbox" name="colors" value="blue" checked/>
<input type="checkbox" name="colors" value="orange" checked/>
<input type="checkbox" name="items" value="chair" checked/>
<input type="checkbox" name="items" value="bed" checked/>
<input type="checkbox" name="material" value="plastic" checked/>
<input type="checkbox" name="material" value="wood" checked/>
</form>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
In case of collecting all grouped checkbox values regardless of their checked
state one just needs to change the above approach slightly too ...
console.log(
Array
.from(
document.querySelectorAll('form [type="checkbox"]')
)
.reduce((result, { name:key, value }) => {
const groupedValueList = (result[key] ??= []);
groupedValueList.push(value);
return result;
}, {})
);
.as-console-wrapper { min-height: 85%!important; }
<form>
<input type="checkbox" name="colors" value="blue" checked/>
<input type="checkbox" name="colors" value="orange"/>
<input type="checkbox" name="items" value="chair" checked/>
<input type="checkbox" name="items" value="bed"/>
<input type="checkbox" name="material" value="plastic" checked/>
<input type="checkbox" name="material" value="wood"/>
</form>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>