I have an input with a datalist. Part of the behavior involves the input being blurred under certain conditions. When I call blur()
however, the datalist doesn't go away like I expect and, even worse, clicking elsewhere on the screen doesn't cause it to go away either; I am forced to either click a different input on screen (not just any other element) or click back into that input and then click away to get it to go away. Am I missing something or is this just unavoidable?
The following is about as minimal as an example can be:
document.getElementById('testinput').addEventListener('input', e => e.target.blur())
<input id="testinput" type="text" list="testlist" />
<datalist id="testlist">
<option>TestOption</option>
</datalist>
Other than unlinking the datalist from the input when I want to blur it, so that it no longer applies, is there anything else I can do to make this work? It seems like very basic behavior.
edit: unlinking alone isn't enough, since the autocomplete suggestions still show up and have the same behavior. You also need autocomplete="off"
in addition to unlinking the datalist to get the expected behavior. Seems like a lot of hassle for what should be default behavior.
To be honest, this is not the best solution, but you can try deleting and returning the list
attribute as needed. Example below:
const element = document.getElementById('testinput');
element.addEventListener('input', e => {
e.target.blur()
});
element.addEventListener('focusin', e => {
e.target.setAttribute('list', 'testlist');
})
element.addEventListener('focusout', e => {
e.target.removeAttribute('list')
});
<input id="testinput" type="text" list="testlist" />
<datalist id="testlist">
<option>TestOption</option>
</datalist>
Or a more compact version, without the focusin
and focusout
events:
const element = document.getElementById('testinput');
element.addEventListener('input', e => {
e.target.removeAttribute('list');
e.target.blur();
setTimeout(() => {
e.target.setAttribute('list', 'testlist');
});
});
<input id="testinput" type="text" list="testlist" />
<datalist id="testlist">
<option>TestOption</option>
</datalist>
With autocomplete
you can try to solve in a similar way (toggling "on" | "off"):
const element = document.getElementById('testinput');
element.addEventListener('input', e => {
e.target.removeAttribute('list');
e.target.setAttribute('autocomplete', 'off');
e.target.blur();
setTimeout(() => {
e.target.setAttribute('list', 'testlist');
e.target.setAttribute('autocomplete', 'on');
});
});
<input id="testinput" type="text" list="testlist" autocomplete="on" />
<datalist id="testlist">
<option>TestOption</option>
</datalist>