How do you grab the value of an optgroup in React

211 Views Asked by At

I have a select dropdown menu that is split by optgroups. For my on change function I also want to record which optgroup the option was picked from. The options are dynamically rendered. I can easily get the value of the selected option but I have no idea how to record the optgroup as well.

Essentially I would love to have a way to have both the option value (e.target.value) and the name of the optgroup it came from to use in a onChange function.

    <div className="">
  <select
    onChange={(e) => {
      console.log(e.target);
    }}
    className=" bg-gray-500"
  >
    <option>Pick Player</option>
    <optgroup label="Substitutes">{subOptions}</optgroup>

    <optgroup label="Reserves"></optgroup>
    {reserveOptions}
    <optgroup label="First Team"></optgroup>
    {firstTeamOptions}
    <optgroup label=""></optgroup>
    <option>+ Add Player</option>
  </select>
</div>
1

There are 1 best solutions below

0
Terry On

The trick is to get the selected <option> element using e.currentTarget.options[e.currentTarget.selectedIndex]. Once you have access to the selected option element:

  1. Use .value to access its value, and
  2. Use .closest('opt group')?.label to access the label of its closest <optgroup> parent. The optional chaining operator will take into account the scenario where the option is not nested inside an <optgroup>.

Proof-of-concept below using JS, but you can easily abstract the logic to the React component's onChange handler:

document.querySelector('select').addEventListener('change', (e) => {
  const {
    selectedIndex,
    options
  } = e.currentTarget;
  const selectedOption = options[selectedIndex];
  const value = selectedOption.value;
  const optgroupLabel = selectedOption.closest('optgroup')?.label;

  console.log({
    value,
    optgroupLabel,
  });
});
<select>
  <option>Pick Player</option>
  <optgroup label="Substitutes">
    <option value="substitutes-1">Substitutes 1</option>
    <option value="substitutes-2">Substitutes 2</option>
  </optgroup>
  <optgroup label="Reserves">
    <option value="reserves-1">Reserves 1</option>
    <option value="reserves-2">Reserves 2</option>
  </optgroup>
  <option>+ Add Player</option>
</select>