Home > database >  Can I put an EventListener on an <option> element?
Can I put an EventListener on an <option> element?

Time:11-11

I am trying to add an EventListener to an <option> Element.

I tried various ways, yet without result. I'm working with VueJS, so I tried to use their event-binding mechanic.

VueJS - Event Binding - works only on <select>

<select @mouseover="testValue = true" @mouseleave="testValue = false" ref="select">
  <option v-for="(option, index) in selectionSet" :key="index"
          :value="option.id" :disabled="option.disabled" @mouseover="testValue = true" @mouseleave="testValue = false">
    {{option.name}}
  </option>
</select>

so naturally I went the RAW plainJS way next.

PlainJS - AddEventListener() - The elements are valid, yet the eventListener will not be registered

this.$refs.select.options.forEach((el) => {
  el.addEventListener('pointerover', () => { window.console.log('AAAAH'); });
  if (!el.disabled) window.console.log(el.value);
});

And yes I went with multiple event names.


So what to do? -> read the docs

Looking into the <option> documentation on MDN, I can see, that the <option> has the HTMLOptionElement DOM Interface. This interface is supposed to have all Properties and Methods inherited from HTMLElement.

The HTMLOptionElement interface represents elements and inherits all properties and methods of the HTMLElement interface. - MDN

So I'm wondering, can I somehow register eventListeners to an <option> Element?

CodePudding user response:

The problem isn't so much registering the event handler on the element, it's that browsers don't fire events at option elements (or at least, not reliably cross-browser) in drop-down select elements.

Chrome and Firefox, for instance, don't fire any events on option elements in drop-down select elements as far as I can tell, even though you can register event handlers on them and even fire your own events on them. In the below, for instance, no events are automatically fired at option elements by Chrome or Firefox, but if you click the button to explicitly fire one at it, it works:

Show code snippet

const option = document.querySelectorAll("option")[1];

function optionEventHandler(event) {
    console.log(event.type, this.textContent);
}

// None of these fire on Chrome except when code explicitly
// does it with `dispatchEvent`, as far as I can tell:
for (const eventName of ["click", "mouseover", "pointerover", "mouseenter"]) {
    option.addEventListener(eventName, optionEventHandler);
}

document.querySelector("select").addEventListener("click", function() {
    console.log("click on select", this.value);
});

// Explicitly firing an event at the element:
document.querySelector("input[type=button]").addEventListener("click", function() {
    option.dispatchEvent(new Event("click"));
});
<select>
<option>A</option>
<option>B</option>
<option>C</option>
<option>D</option>
<option>E</option>
</select>
<div>
    <input type="button" value="Send 'click' to B">
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

So sadly, if you want to do something when the pointer is over the option, you'll have to use something other than select and option. Neither Chrome nor Firefox even fires pointerover at document when the pointer moves from one option to the next in a list.

For completeness, note that some events (including pointerover) work in non-dropdown select elements, at least on Chrome and Firefox:

Show code snippet

const option = document.querySelectorAll("option")[1];

function optionEventHandler(event) {
    console.log(event.type, this.textContent);
}

// None of these fire on Chrome except when code explicitly
// does it with `dispatchEvent`, as far as I can tell:
for (const eventName of ["click", "mouseover", "pointerover", "mouseenter"]) {
    option.addEventListener(eventName, optionEventHandler);
}

document.querySelector("select").addEventListener("click", function() {
    console.log("click on select", this.value);
});

// Explicitly firing an event at the element:
document.querySelector("input[type=button]").addEventListener("click", function() {
    option.dispatchEvent(new Event("click"));
});
<select size="5">
<option>A</option>
<option>B</option>
<option>C</option>
<option>D</option>
<option>E</option>
</select>
<div>
    <input type="button" value="Send 'click' to B">
</div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related