Search code examples
javascripthtmlhtml-selecthtmlelements

HTMLOptionElement: onclick event doesn't trigger


I want a select element to contain one default option that shows a popup when selected. So I've created HTMLOptionElement and add an event to onclick event listener but the event doesn't trigger when the option is clicked.

Here is my code:

const selectDefaultOption = new Option(".. show popup ...");
selectDefaultOption.addEventListener("mouseup", () => {
    // ... show pop up
});
document.querySelector("#select").appendChild(selectDefaultOption);

Am I doing something wrong? Or it's not possible to achieve what I'm trying to?

Conclusion & Solution

After a few attempts I came to the conclusion that there is no neat solution to simply trigger event attached to a select option.

However, I've managed to achieve performing an action when specific option is selected (although it's not as elegant as was my initial intention).

The solution:

const selectElement = document.querySelector("#select");

const placeholderOption = new Option("<< select option >>", "<< select option >>", true, true);
placeholderOption.style.display = "none"; // this option is never display in the selection and serves only as a placeholder
selectElement.add(placeholderOption, null);

const onclickOption = new Option("onclick option", "onclick option")
onclickOption.onclick = () => alert("onlick option clicked!");
selectElement.add(onclickOption, null);

let previousSelectedValue;
selectElement.onmouseenter = event => {
  previousSelectedValue = event.target.value;
  event.target.value = placeholderOption.value;
  event.target.onmouseleave = event => {
    event.target.value = previousSelectedValue;
  };
} 
selectElement.oninput = event => {    
  event.target.onmouseleave = undefined; // reset the onmouseleave so it doesn't change current value
  const selectedOption = event.target.selectedOptions[0];
  if (selectedOption.onclick){
    selectedOption.onclick(selectedOption.event); 
    event.target.value = previousSelectedValue; // you may assign placeholderOption.value
  }
};
<select id="select">
    <option>option#1</option>
    <option>option#2</option>
</select>


Solution

  • First I add eventListener to the select container. As trigger i took focus. Then i use your code to create a new option element. This element i assign a new eventListener which trigger the alert().

    Update for all Browsers

    The assigned EventListener on options tags on a created element will fail on most browsers. That is why it is right to tie the EventListerner to the Select Tag. Then you can check which field it is via the value field.

    const s = document.getElementById('select');
    let isLoaded = false;
    
    s.addEventListener('focus', () => {  
      if (! isLoaded) {
        const selectDefaultOption = new Option(".. show popup ...");    
        selectDefaultOption.setAttribute('value', "popup");
        s.appendChild(selectDefaultOption);
      }
      isLoaded = true;
    });
    
    function callPopUp(event) {
      let s = document.getElementById('select');
      if (s.value === 'popup') {
        alert('PopUp')
      }
    }
    select {
      width: 200px;
      background: gray;
      padding:10px;
    }
    <select id="select" onclick='callPopUp(event)'>
      <option value="123">123</option>  
      <option value="456">456</option>  
    </select>

    Note

    Together with @Olafvolafka we found out that in most browsers (Chrome, Opera) it is not possible to successfully bind an event to the option tag / element. No event was triggered. Only in Firefox was an event triggered. Therefore, we have to work with a workaround. Status 01/2022.