Search code examples
javascriptinternet-explorer-10dom-eventshtml-datalist

Internet explorer 10 "input" event on datalist option selection not firing


In the following example I have an input field and accompanying datalist element. I am trying to write javascript that listens for when a user selects an item from the list. I have seen it suggested to use the "input" event for this, and in Chrome, Firefox, etc it all works. The problem is internet explorer.

In IE10 I get the following behavior:

  • Typing in the field fires the event.
  • Selecting an item from the datalist does not fire the event the first time.
  • Reselecting the same option does fire the event.

See test:

enter image description here

$('input').on('input', function(){
    console.log($('input').val());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input list="ice-cream-flavors" id="ice-cream-choice" name="ice-cream-choice" />

<datalist id="ice-cream-flavors">
    <option value="Chocolate">
    <option value="Coconut">
    <option value="Mint">
    <option value="Strawberry">
    <option value="Vanilla">
</datalist>

Does anyone have any suggestions on how I can force internet explorer to fire that (or any) event so I can run a function when a user makes a selection?


Solution

  • I ran into the same issue on IE11 with a custom autocomplete list made based on this: https://www.w3schools.com/howto/howto_js_autocomplete.asp

    Some testing showed that IE11 fired the input event when clicking away from the input box (i.e. when losing focus). The intended behaviour, as in other browsers, was to only fire this event on text entry (including backspace) into the input field.

    The solution was to check whether the input value had changed in IE, like this:

    function inputEventGeneral(input, fn) { //input event for any browser
        if (checkBrowserIE()) {
            inputEventIE(input, fn);
        } else {
            input.addEventListener('input', function (e) { //normal input event for Chrome, FF, etc.
                fn(this); //run this function on input
            });
        };
    };
    
    function inputEventIE(input, fn) { //input event for IE
        let curr = '';
        let prev = '';
    
        input.addEventListener('input', function (e) {
            curr = this.value;
    
            if (prev === curr) { //check if value changed
                return;
            };
    
            prev = curr; //update value of prev
    
            fn(this); //run this function only if the value has been changed
        });
    };
    
    
    function checkBrowserIE() {
        return (/Trident/.test(navigator.userAgent)); //https://stackoverflow.com/questions/22004381/ie-input-event-for-contenteditable
    };
    

    In IE, there is also the issue of the 'x' clear button on the text input field, which would not fire an input event when using the above code. For this, you could either a) simply hide that clear button with CSS, as below:

    input[type=text]::-ms-clear { display: none; }
    

    or b) you could modify the above code to store the value of prev in a data-prev attribute or a global variable, and then update it with any changes of the input form value (e.g. when selecting from the autocomplete list/datalist). This would then cause the event to fire on clicking the clear button, because the prev value (val) would be different from the curr value ('') when clearing.

    Hope that helps!