Change <select>'s option and trigger events with JavaScript

How can I change an HTML <select>'s option with JavaScript (without any libraries like jQuery), while triggering the same events as if a user had made the change?

For example using following code, if I change the option with my mouse then an event triggers (i.e. onchange is run). However, when I change the option using JavaScript then it doesn't fire any event. Is it possible to fire trigger associated event handlers like onclick, onchange, etc., when an option is selected with JavaScript?

<select id="sel" onchange='alert("changed")'>
<option value='1'>One</option>
<option value='2'>Two</option>
<option value='3'>Three</option>
</select>
<input type="button" onclick='document.getElementById("sel").options[1].selected = true;' value="Change option to 2" />

http://jsfiddle.net/xwywvd1a/

189678 次浏览

You can fire the event manually after changing the selected option on the onclick event doing: document.getElementById("sel").onchange();

Try this:

<select id="sel">
<option value='1'>One</option>
<option value='2'>Two</option>
<option value='3'>Three</option>
</select>




<input type="button" value="Change option to 2"  onclick="changeOpt()"/>


<script>


function changeOpt(){
document.getElementById("sel").options[1].selected = true;


alert("changed")
}


</script>

These questions may be relevant to what you're asking for:

Here are my thoughts: You can stack up more than one call in your onclick event like this:

<select id="sel" onchange='alert("changed")'>
<option value='1'>One</option>
<option value='2'>Two</option>
<option value='3'>Three</option>
</select>
<input type="button" onclick='document.getElementById("sel").options[1].selected = true; alert("changed");' value="Change option to 2" />

You could also call a function to do this.

If you really want to call one function and have both behave the same way, I think something like this should work. It doesn't really follow the best practice of "Functions should do one thing and do it well", but it does allow you to call one function to handle both ways of changing the dropdown. Basically I pass (value) on the onchange event and (null, index of option) on the onclick event.

Here is the codepen: http://codepen.io/mmaynar1/pen/ZYJaaj

<select id="sel" onchange='doThisOnChange(this.value)'>
<option value='1'>One</option>
<option value='2'>Two</option>
<option value='3'>Three</option>
</select>
<input type="button" onclick='doThisOnChange(null,1);' value="Change option to 2"/>


<script>
doThisOnChange = function( value, optionIndex)
{
if ( optionIndex != null )
{
var option = document.getElementById( "sel" ).options[optionIndex];
option.selected = true;
value = option.value;
}
alert( "Do something with the value: " + value );
}
</script>

Fiddle of my solution is here. But just in case it expires I will paste the code as well.

HTML:

<select id="sel">
<option value='1'>One</option>
<option value='2'>Two</option>
<option value='3'>Three</option>
</select>
<input type="button" id="button" value="Change option to 2" />

JS:

var sel = document.getElementById('sel'),
button = document.getElementById('button');


button.addEventListener('click', function (e) {
sel.options[1].selected = true;


// firing the event properly according to StackOverflow
// http://stackoverflow.com/questions/2856513/how-can-i-trigger-an-onchange-event-manually
if ("createEvent" in document) {
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
sel.dispatchEvent(evt);
}
else {
sel.fireEvent("onchange");
}
});


sel.addEventListener('change', function (e) {
alert('changed');
});

It is as simple as this:

var sel = document.getElementById('sel');
var button = document.getElementById('button');


button.addEventListener('click', function (e) {
sel.options[1].selected = true;
sel.onchange();
});

But this way has a problem. You can't call events just like you would, with normal functions, because there may be more than one function listening for an event, and they can get set in several different ways.

Unfortunately, the 'right way' to fire an event is not so easy because you have to do it differently in Internet Explorer (using document.createEventObject) and Firefox (using document.createEvent("HTMLEvents"))

var sel = document.getElementById('sel');
var button = document.getElementById('button');


button.addEventListener('click', function (e) {
sel.options[1].selected = true;
fireEvent(sel,'change');


});




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);
}
}

Unfortunately, you need to manually fire the change event. And using the Event Constructor will be the best solution.

var select = document.querySelector('#sel'),
input = document.querySelector('input[type="button"]');
select.addEventListener('change',function(){
alert('changed');
});
input.addEventListener('click',function(){
select.value = 2;
select.dispatchEvent(new Event('change'));
});
<select id="sel" onchange='alert("changed")'>
<option value='1'>One</option>
<option value='2'>Two</option>
<option value='3' selected>Three</option>
</select>
<input type="button" value="Change option to 2" />

And, of course, the Event constructor is not supported in IE. So you may need to polyfill with this:

function Event( event, params ) {
params = params || { bubbles: false, cancelable: false, detail: undefined };
var evt = document.createEvent( 'CustomEvent' );
evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
return evt;
}

The whole creating and dispatching events works, but since you are using the onchange attribute, your life can be a little simpler:

http://jsfiddle.net/xwywvd1a/3/

var selEl = document.getElementById("sel");
selEl.options[1].selected = true;
selEl.onchange();

If you use the browser's event API (addEventListener, IE's AttachEvent, etc), then you will need to create and dispatch events as others have pointed out already.

html using Razor:

 @Html.DropDownList("test1", Model.SelectOptionList, new { id = "test1", onchange = "myFunction()" })

JS Code:

function myFunction() {


var value = document.getElementById('test1').value;


console.log("it has been changed! to " + value );
}