skip to Main Content

I have defined a searchable select list, as defined below. What I would like is to get the data-value field once a selection is made, while the user will still see the option value string. This field will contain the internal id of the entry.

If I define this id, as a value attribute, the dropdown list will show both the id and the string , and after selection only the id will be visible in the input field.

I’ve found some posts taking about using data-* attributes to work around this problem, but for some reasons, I’m not able to get this value from the input field, after the selection was completed.

Any idea how I can achieve this?

Thanks

PS: I’m only interested in pure JavaScript solutions.

<html>
<head>
<script>
function onchangeTest(){
alert(document.getElementById("input").value);
}
</script>
</head>
<body>
    <div id="share">
        <input type="text" id="input" list="datalist" onchange="onchangeTest()">

        <datalist id="datalist">
           <option data-value="1">Foo</option>
           <option data-value="2">Bar</option>
           <option data-value="3">Baz</option>
           <option data-value="4">Foo Bar</option>
           <option data-value="5">Bar Baz</option>
        </datalist>
    </div>

</body>
</html>

3

Answers


  1. Chosen as BEST ANSWER

    For whoever will be interested in the future, I've ended up dropping the input datalist approach and picked this search dropdown list implementation instead:

    https://github.com/Godsont/Custom-Select-Box-with-Search


  2. You can check all the options to find the option with a matching value (if any), then read from its dataset.

    document.getElementById('input').addEventListener('change', function(e) {
      const option = [...this.list.options]
                      .find(x => x.value === this.value);
      console.log(option?.dataset.id); 
      // may be undefined, as user can manually type text
    });
    <div id="share">
      <input type="text" id="input" list="datalist" />
      <datalist id="datalist">
         <option data-id="1">Foo</option>
         <option data-id="2">Bar</option>
         <option data-id="3">Baz</option>
         <option data-id="4">Foo Bar</option>
         <option data-id="5">Bar Baz</option>
      </datalist>
    </div>
    Login or Signup to reply.
  3. In the event handler function, you can loop through the options in the datalist, compare the input value with the option’s text content, and retrieve the data-value attribute when there’s a match:

    function onchangeTest() {
      let input = document.getElementById("input");
      let datalist = document.getElementById("datalist");
      let options = datalist.querySelectorAll("option");
    
      for (let option of options) {
        if (option.textContent === input.value) {
          let dataValue = option.getAttribute("data-value");
          alert(dataValue);
          break;
        }
      }
    }
    <div id="share">
      <input type="text" id="input" list="datalist" onchange="onchangeTest()">
    
      <datalist id="datalist">
        <option data-value="1">Foo</option>
        <option data-value="2">Bar</option>
        <option data-value="3">Baz</option>
        <option data-value="4">Foo Bar</option>
        <option data-value="5">Bar Baz</option>
      </datalist>
    </div>

    I see two problems with this approach

    • The options.textContent should be unique to always work expected
    • Since you are checking onchange this might slow down your frontend performance with a large list. If this problem occurs I recommend you to use the debounce technique to prevent excessive function calls while typing.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search