How do I get the change event for a datalist?
The solutions above all have a big problem. If the datalist has the option of (for example) "bob" and "bobby", as soon as someone types "bob", they code immediately says it's the same as clicking "bob"... but what if they were attempting to type "bobby"?
For a better solution, we need some more information. When listening for the 'input' event on the input field:
In Chromium-based browsers, when you type, delete, backspace, cut, paste, etc. in an input field, the event that is passed to the handler is an InputEvent
, whereas when you select an option from the datalist, the event is just an Event
type with a property of type
that equals 'input'. (This is also true during an auto-fill, at least with BitWarden).
So you can listen for an 'input' event and check to see if it's an instance of InputEvent
to determine if it's from autofill (which I think should be allowed since most of the time autofill won't be filling these types of fields, and if they do, it's usually a legit choice) / datalist selection.
In Firefox, it's different, though. It still provides an InputEvent
, but it has an inputType
property with the value of "insertReplacementText", which we can also use. Autofill does the same thing as Chromium browsers.
So here's a better solution:
$('#yourInput').on('input', function(){
if (
!(e instanceof InputEvent) ||
e.inputType === 'insertReplacementText')
) {
// determine if the value is in the datalist. If so, someone selected a value in the list!
}
});
I wish the browsers had the same implementation that had an event type/property that was exclusive to datalist selection, but they don't so this is the best I've got. I haven't tested this on Safari (I don't have access or time right now) so you should probably take a look at it and see if it's the same or has other distinguishing differences.
UPDATE:
I noticed that if you already have the full word typed up (e.g. you typed in "Firefox") and then selected the option that matched what you had typed (e.g. you selected the "Firefox" option), it would not fire an "input" event, so you would not know that one of the options was chosen at that point. So, you'll also need a keydown/keypress/keyup event listener to listen to when they press enter. In Chromium browsers, though, it actually provides a key code
of undefined
when you hit enter or click on an option (yes, the click makes a keyup event). In Firefox, it says you hit Enter, but it doesn't fire any events I can find when you click an option.
You can manually check it on change. But you need to check change of the input of datalist.
$(document).on('change', 'input', function(){
var options = $('datalist')[0].options;
var val = $(this).val();
for (var i=0;i<options.length;i++){
if (options[i].value === val) {
alert(val);
break;
}
}
});
FIDDLE
In browser with the inputType property on the InputEvent you can use that to filter out any unwanted onInput events. This is "insertReplacementText" on Firefox 81 and null for Chrome/Edge 86. If you need to support IE11 you will need to validate the value is valid.
document.getElementById("browser")
.addEventListener("input", function(event){
if(event.inputType == "insertReplacementText" || event.inputType == null) {
document.getElementById("output").textContent = event.target.value;
event.target.value = "";
}
})
<label for="browser">Choose your browser from the list:</label>
<input list="browsers" name="browser" id="browser">
<datalist id="browsers">
<option value="Edge">
<option value="Firefox">
<option value="Chrome">
<option value="Opera">
<option value="Safari">
</datalist>
<div id="output">
</div>