skip to Main Content

Is there a way to trigger a JavaScript event specifically after selecting a datalist option? By that I don’t mean if any input has been entered, or even if an input identical to an option in the datalist has been typed in manually.

I only want it to trigger if you specifically CLICK the option from the datalist displayed.

I tried $('#search-data').click() and $('#search-data options').click(), but neither triggered.

$('#search-options').click(function(){
  alert("test");
});

$('#search-options options').click(function(){
  alert("test 2");
});
<datalist id="search-options">
  <option>Test1</option>
  <option>Test2</option>
</datalist>

<input id="search-bar" type="text" list="search-options" class="form-control" placeholder="Search" aria-label="Search">


<script src="https://code.jquery.com/jquery-3.7.0.js" integrity="sha256-JlqSTELeR4TLqP0OG9dxM7yDPqX1ox/HfgiSLBj8+kM=" crossorigin="anonymous"></script>

3

Answers


  1. Listen for the blur event on the <input> element when the <input> loses focus, capture the entered value then check if it matches any of the <option>s.

    $("#search-bar").on("blur", function () {
       var inputText = $(this).val();
       var optionFound = false;
    
       $("#search-options option").each(function () {
          if ($(this).text() === inputText) {
             optionFound = true;
             return false;
          }
       });
    
       if (optionFound) {
          alert("Option selected: " + inputText);
       }
    });
    <datalist id="search-options">
        <option>Test1</option>
        <option>Test2</option>
    </datalist>
    
    <input id="search-bar" type="text" list="search-options" class="form-control" placeholder="Search" aria-label="Search" />
    
    <script src="https://code.jquery.com/jquery-3.7.0.js" integrity="sha256-JlqSTELeR4TLqP0OG9dxM7yDPqX1ox/HfgiSLBj8+kM=" crossorigin="anonymous"></script>

    The same solution can work with any other event, like the input event, change event, etc. Choose the one that matches your expectations I guess.

    Login or Signup to reply.
  2. If you don’t need to check if any input has been entered, or if an input identical to an option in the datalist has been typed in manually, you can try this.

    var textbox = document.getElementById("search-bar");
    textbox.addEventListener(
      "input",
      function (e) {
        var isInputEvent =
          Object.prototype.toString.call(e).indexOf("InputEvent") > -1;
        // If the type is not InputEvent, then an option was selected from the datalist
        if (!isInputEvent) alert(e.target.value);
      },
      false
    );
    <datalist id="search-options">
      <option>Test1</option>
      <option>Test2</option>
    </datalist>
    
    <input id="search-bar" type="text" list="search-options" class="form-control" placeholder="Search" aria-label="Search">

    This solution uses the input event and checks the type of the event object. If the type is not InputEvent, then it means that the input event was caused by a datalist option selection, not by keyboard input, mouse input, or paste input. By using this approach, you can trigger a JavaScript event specifically after selecting a datalist option.

    Login or Signup to reply.
  3. So the issues are:

    1. You can’t target the options with selectors
    2. The change/input events will fire regardless of if the input was changed from the keyboard, clipboard, or picking an option

    I added a bunch of listeners to a datalist: keyup, keydown, paste, input, change and observed the following:

    Clicking on an item in the datalist triggers a keyup event with an empty (undefined) keycode, followed by whatever other events are related to the input changing, followed by a keydown event with an empty keycode.

    Pasting will trigger a paste event, typing will trigger a key event that is non-undefined. So create a listener for all of the events, and then check whenever we see this pattern:

        undefined keydown 
        + (input and change event when value changed OR no event when value did not change)
        + undefined keyup
    

    Log each heard event in an array, and then check the array for a valid chain.

    Disclaimer
    This seems to work, but its hacky, subject to breaking, and only tested in chrome

    let eventQueue = [];
    let foundKeydown = false;
    const $search = $('#search-bar');
    $search.on('paste change input keyup keydown', event => {
    // if the event type is not keyup or keydown, log it
        if (event.type !== 'keyup' && event.type !== 'keydown') {
            eventQueue.push(event.type);
        }
        if (event.type === 'keydown' && !event.keyCode) {
            // drop everything prior in the eventQueue. 
            //this is the start of a potential option click
            eventQueue = [];
            foundKeydown = true;
        }
        if (event.type === 'keyup' && !event.keyCode && foundKeydown === true) {
            // this is the end of a potential click.
            foundKeydown = false;
            // check that the queue contains:
            if (
                // 1. no paste or key events
                eventQueue.every(type => type !== 'paste' && type !== 'keyup' && type !== 'keydown')
                // and
                && (
                    // 1. either an input+change event
                    (eventQueue.some(type => type === 'change') && eventQueue.some(type => type === 'input'))
                    // or neither
                    || eventQueue.every(type => type !== 'change' && type !== 'input')
                )
            ) {
                console.log('clicked a data option:', event.target.value);
            }
    
        }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <datalist id="search-options">
      <option>Test1</option>
      <option>Test2</option>
    </datalist>
    <input id="search-bar" type="text" list="search-options">
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search