0

If I have the following select:

<select id="multi_select" multiple>
    <option id="1" value="one">One</option>
    <option id="2" value="two">Two</option>
    <option id="3" value="three">Three</option>
    <option id="4" value="four">Four</option>
    <option id="5" value="five">Five</option>
</select>

How can I get the id of the clicked option element?

If I use this:

$("#multi_select").on('change', function () {
    let id = this.options[this.selectedIndex].id;
});

It doesn't work, because it returns the top most id.

In my example, if I click option One and then I shift-click option Two (select multiple), the id would be 1 because it's the top most selected option, but I need only the id of the option that was clicked on


Edit Added snippet

$("#multi_select").on('change', function() {
  let id = this.options[this.selectedIndex].id;
  console.log(id);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="multi_select" multiple>
        <option id="1" value="one">One</option>
        <option id="2" value="two">Two</option>
        <option id="3" value="three">Three</option>
        <option id="4" value="four">Four</option>
        <option id="5" value="five">Five</option>
</select>
pileup
  • 1
  • 2
  • 18
  • 45
  • So you would need to have to loop over all of the options and see if it is selected. – epascarello Nov 17 '22 at 16:16
  • Your code, as provided, does not do as described. https://jsfiddle.net/7dqpbx0j/ When I click on "one" if gives 1 then "two" gives 2. The `change` event (which you're using) occurs after the element has changed. If you used `.on("click"` then yes, you'd get that issue. – freedomn-m Nov 17 '22 at 16:29
  • *In my example, if I click option One and then I click option Two, the id would be 1* - that's not what happens, try the snippet/fiddle. If you change to `click` event then you'd get the *previous* selection, not the first one - try with a larger test sample than just two entries. – freedomn-m Nov 17 '22 at 16:30
  • 1
    @freedomn-m make sure you select multiple, not just click them, also added more options – pileup Nov 17 '22 at 16:33
  • 1
    @B.DLiroy right, that's relevant that should have been in the question. "click option two" is different from "shift-click option 2". – freedomn-m Nov 17 '22 at 16:41
  • To get *all* IDs (to same more duplicate answers), see: [How to get multiple select box values](https://stackoverflow.com/questions/3243476/how-to-get-multiple-select-box-values-using-jquery) – freedomn-m Nov 17 '22 at 16:42
  • @freedomn-m no problem, I will add that to the post and edit the title as well – pileup Nov 17 '22 at 16:42
  • 1
    You need to either use `click` event or keep a record of values since the last `change` and compare them. – freedomn-m Nov 17 '22 at 16:43
  • 1
    https://stackoverflow.com/a/42887557/2181514 – freedomn-m Nov 17 '22 at 16:45
  • @freedomn-m it actually works well for the value, but I could not make it work for the `id` from some reason – pileup Nov 17 '22 at 17:18
  • 1
    Who deleted my comment? Code works just fine ... – VXp Nov 17 '22 at 19:31
  • @VXp I did not see your comment – pileup Nov 17 '22 at 19:37
  • I wrote "I think it works." and some genius deleted it. – VXp Nov 17 '22 at 19:39

3 Answers3

3

Select the options that are checked and loop over to get all of the ids.

document.querySelector("#multi_select").addEventListener("change", (evt) => {
  const selectedIds = [...evt.target.querySelectorAll('option:checked')].map(({
    id
  }) => id);
  console.log(selectedIds);
});


/*
document.querySelector("#multi_select").addEventListener("change", function(evt) {
  const selectedIds = Array.from(evt.target.querySelectorAll('option:checked')).map(function(opt) {
    return opt.id
  });
  console.log(selectedIds);
});
*/
<select id="multi_select" multiple>
  <option id="1" value="one">One</option>
  <option id="2" value="two">Two</option>
</select>

Seeing what the use selected is comparing what you had before and what you have now.

document.querySelector("#multi_select").addEventListener("change", (evt) => {
  
  const prevIds = JSON.parse(evt.target.dataset.prevSelectedIds || '[]');
  
  const selectedIds = [...evt.target.querySelectorAll('option:checked')].map(({
    id
  }) => id);
  
  evt.target.dataset.prevSelectedIds = JSON.stringify(selectedIds);
  
  // find out the new selection)
  if (selectedIds.length > prevIds.length) {
    const newlySelected = selectedIds.filter(id => !prevIds.includes(id))
    console.log("added", newlySelected);
  } else {
    // this is showing what is now selected
    console.log("selected", selectedIds);

   // You can do a reverse of the if to see what is not there
   const newlyUnselected = prevIds.filter(id => !selectedIds.includes(id))
   console.log("unselected", newlyUnselected);

  }
});
<select id="multi_select" multiple>
  <option id="1" value="one">One</option>
  <option id="2" value="two">Two</option>
</select>
epascarello
  • 204,599
  • 20
  • 195
  • 236
0

Try this out:

$("#multi_select").change(function() {
  var id = $(this).children(":selected").attr("id");
});
0

Here you can try this logic :

let selectedOpt = [];
      function check(ev) {
        for (let item of ev.target.options) {
          if (item.selected) {
            selectedOpt.push(item);
          }
        }

        // here we got finally selected options
        console.log(selectedOpt);

        //here array iteration can be done
        for (let opt of selectedOpt) {
          console.log(opt.id, opt.value);
        }
      }
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <select onchange="check(event)" multiple>
      <option id="1" value="one">One</option>
      <option id="2" value="two">Two</option>
      <option id="3" value="three">three</option>
      <option id="4" value="four">four</option>
      <option id="5" value="five">five</option>
    </select>

   
  </body>
</html>
Jerry
  • 1,005
  • 2
  • 13