Search code examples
javascriptdom-eventshtml-selectdispatchevent

How can I add a 'change' event listener for a styled select?


Obviously, if I have a 'select' element, I can add an event listener for changes using some basic JS:

document.querySelector('select').addEventListener('change', function(ev){
  console.log('Changed', ev.target.value)
})

Click the 'select' element, modify the value, the log fires. Simple stuff.

However I'm working on a library for styled select boxes - like chosen or select2 without the jQuery dependency.

In my library, clicking the styled select box changes the .value of the real select box:

query('select').value = newValue;

I can see this is working if I make the real select box visible.

However, changing the value of the select box through JS doesn't trigger the select boxes 'change' event.

Is there a way I can change the select boxes value though JS and still have change events attached to the select box fire?


Solution

  • Javascript

    function fireEvent(element, event) {
        if (document.createEventObject) {
            // dispatch for IE
            var evt = document.createEventObject();
            return element.fireEvent('on' + event, evt)
        } else {
            // dispatch for firefox + others
            var evt = document.createEvent("HTMLEvents");
            evt.initEvent(event, true, true); // event type,bubbling,cancelable
            return !element.dispatchEvent(evt);
        }
    }
    
    document.querySelector('select').addEventListener('change', function (ev) {
        console.log('Changed', ev.target.value)
    });
    
    btn.onclick = function () {
        select.selectedIndex = 2;
        var obj = document.querySelector('select');
        fireEvent(obj, 'change');
    }
    

    User call

    var yourPlugin=new CustomSelect(options);
    yourPlugin.value("3");
    

    Plugin function

    function value(val) {
        if (!val) return select.value;
        select.value = val;
        fireEvent(select, 'change');
    }
    

    DEMO