-1

Say I want an object with this format

    var optgroups = [
    {
      name: "Cat1",
      options: [
        { text: "item1", value: "1" },
        { text: "item4", value: "4" },
      ],
    },
    { name: "Cat2", options: [{ text: "item2", value: "2" }] },
    { name: "Cat3", options: [{ text: "item3", value: "3" }] },
    ];

And I want to create it based on what's already populated in a select element in a form

<select>
   <optgroup label="Cat1">
      <option value="1">item1</option>
      <option value="4">item4</option>
   </optgroup>
   <optgroup label="Cat2">
      <option value="2">item2</option>
   </optgroup>
   <optgroup label="Cat3">
      <option value="3">item3</option>
   </optgroup>
 </select>

What JavaScript code (jQuery is also an option) would achieve such an object?

This is an old code base so things like React/Vue are not an option.

Unmitigated
  • 76,500
  • 11
  • 62
  • 80
nacho10f
  • 5,816
  • 6
  • 42
  • 73
  • Just loop through the HTML elements. – Geshode Jul 21 '20 at 02:33
  • Familiarize yourself with [how to access and process nested objects and arrays](https://stackoverflow.com/q/11922383/4642212), use the available [`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#Methods_of_the_Object_constructor), [`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#Methods) and [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) methods. – Sebastian Simon Jul 21 '20 at 02:33

2 Answers2

1

You can use document.querySelectorAll to get all the <optgroup> elements to loop over and use it again to find all the options.

const optgroups = [];
document.querySelectorAll("#mySelect > optgroup").forEach(group=>{
  const obj = {name: group.label, options: []};
  group.querySelectorAll('option').forEach(option=>{
    obj.options.push({text: option.textContent, value: option.value});
  });
  optgroups.push(obj);
});
console.log(optgroups);
<select id="mySelect">
  <optgroup label="Cat1">
    <option value="1">item1</option>
    <option value="4">item4</option>
  </optgroup>
  <optgroup label="Cat2">
    <option value="2">item2</option>
  </optgroup>
  <optgroup label="Cat3">
    <option value="3">item3</option>
  </optgroup>
</select>
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
1

Here's what I ended up using thanks to @hev1

  const optgroups = [
    ...document.querySelectorAll("#mySelect > optgroup"),
  ].map((group) => ({
    name: group.label,
    options: [...group.querySelectorAll("option")].map((opt) => ({
      text: opt.textContent,
      value: opt.value,
    })),
  }));
nacho10f
  • 5,816
  • 6
  • 42
  • 73