The multiple attribute (specification) on an <input> element is used to indicate that multiple values can be selected. However, browsers don't support this attribute when using a <datalist> element. Only one element will be suggested.
Let's improve input to support datalists and multiple values! Here's the final result:Source code of the demo: demo.zip
HTML
<input type="text" list="Suggestions" multiple />
<datalist id="Suggestions">
<option>option 1</option>
<option>option 2</option>
<option>option 3</option>
</datalist>
The idea is to dynamically edit the option element of the datalist while you are typing to remove selected values and prefix all others with the already selected values. For instance, if the input value is option 2,, the HTML will be:
HTML
<input type="text" list="Suggestions" multiple value="option 2," />
<datalist id="Suggestions">
<option>option 2, option 1</option>
<option>option 2, option 3</option>
</datalist>

Here's the TypeScript code to dynamically update the datalist's children:
TypeScript
document.addEventListener("DOMContentLoaded", function () {
const separator = ',';
for (const input of document.getElementsByTagName("input")) {
if (!input.multiple) {
continue;
}
if (input.list instanceof HTMLDataListElement) {
const optionsValues = Array.from(input.list.options).map(opt => opt.value);
let valueCount = input.value.split(separator).length;
input.addEventListener("input", () => {
const currentValueCount = input.value.split(separator).length;
// Do not update list if the user doesn't add/remove a separator
// Current value: "a, b, c"; New value: "a, b, cd" => Do not change the list
// Current value: "a, b, c"; New value: "a, b, c," => Update the list
// Current value: "a, b, c"; New value: "a, b" => Update the list
if (valueCount !== currentValueCount) {
const lsIndex = input.value.lastIndexOf(separator);
const str = lsIndex !== -1 ? input.value.substr(0, lsIndex) + separator : "";
filldatalist(input, optionsValues, str);
valueCount = currentValueCount;
}
});
}
}
function filldatalist(input: HTMLInputElement, optionValues: string[], optionPrefix: string) {
const list = input.list;
if (list && optionValues.length > 0) {
list.innerHTML = "";
const usedOptions = optionPrefix.split(separator).map(value => value.trim());
for (const optionsValue of optionValues) {
if (usedOptions.indexOf(optionsValue) < 0) { // Skip used values
const option = document.createElement("option");
option.value = optionPrefix + optionsValue;
list.append(option);
}
}
}
}
});
When you add this script in your page it should detect input with the multiple attribute and update its behavior with the datalist.
Do you have a question or a suggestion about this post? Contact me!