I'm working on extending the input element to use the nice datalist autocomplete functionality, but restrict only to the elements in the datalist, much like a select. Problem is I need the data attributes from the options in the datalist.
The search brings up a lot of failed attempts, including this one with an accepted answer that seems to imply you get get the data attributes from the input element, but that's not the case in my testing. The best I've found is getting the value of the input on 'insertReplacementText' and searching the associated dataset, but I was wondering if there's a more straightforward solution.
That also doesn't work with duplicate dataset values, but I can force them to be unique if that's my only choice.
Here's my test code:
<script>
class MyInputListElement extends HTMLInputElement {
constructor() {
// Always call super first in constructor
self = super();
}
connectedCallback() {
// Dump everything for testing
for (let o of this.list.options)
{
for (let d in o.dataset)
{
console.log(o.value + ": " + d + " " + o.dataset[d]);
}
}
this.addEventListener('change', () => {
console.log("change: " + this.dataset);
for (let d in this.dataset)
{
console.log(d + " " + this.dataset[d]);
}
});
this.addEventListener('input', () => {
console.log("input: " + this.dataset)
for (let d in this.dataset)
{
console.log(d + " " + this.dataset[d]);
}
});
}
attriuteChangedCallback(name, oldValue, newValue) {
}
}
customElements.define("my-list-input", MyInputListElement, {extends: "input"});
</script>
<datalist id="ice">
<option value="Chocolate" data-test1="chicken" data-test2="parm"></option>
<option value="Coconut"></option>
<option value="Mint"></option>
<option value="Strawberry"></option>
<option value="Vanilla"></option>
</datalist>
<input is="my-list-input" list="ice" id="mylist">
Output after clicking in the input box and selecting Chocolate:
Chocolate: test1 chicken test.php:86:14
Chocolate: test2 parm test.php:86:14
input: [object DOMStringMap] test.php:97:13
change: [object DOMStringMap] test.php:90:13
I was wondering if we could hook into the selection box that pops up when you click the input box, but I don't see it appear in the DOM.
Has anyone figured this out yet in 2024 or is a value search through the datalist still the only way?
Edit: just for completeness, here's a working implementation of the lookup method. This makes it work very much like a select, but with the dataset style typing ahead.
class MyInputListElement extends HTMLInputElement {
constructor() {
// Always call super first in constructor
self = super();
this.curSel = '';
}
connectedCallback() {
this.addEventListener('change', () => {
this.value = this.curSel;
});
this.addEventListener('input', (e) => {
if (event.inputType === 'insertReplacementText')
{
// This means the user selected a value, so set it as our
// current selection to fall back on if they navigate away
this.curSel = this.value;
// Now find a matching datalist item and grab its dataset
for (let opt of this.list.options) {
if (opt.value === this.value) {
// Got 'em. Now clear our dataset and add the option's
for (let d in this.dataset) {
delete this.dataset[d];
}
for (let d in opt.dataset) {
this.dataset[d] = opt.dataset[d];
}
break;
}
}
console.log(this.dataset);
}
});
}
attriuteChangedCallback(name, oldValue, newValue) {
}
}
this.dataset, butthisseems to be the input, which doesn't have anydata-attributes. Curious: why did you choose a datalist instead of a select?