I have hit a weird case where, to the best of my knowledge, two things that should act the same behave quite differently.
If I have two select menus on a page, one static menu hardcoded in the HTML and one appended to the body at runtime with JQuery. I then disable the first option in both select menus. When displayed both menus have their first options disabled as expected, however the dynamically appended menu has automatically set the value to the second option while the static menu still has the first selected.
http://jsfiddle.net/hm3xgkLg/1/
HTML:
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
Javascript:
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function() {
sel.append($("<option>").attr('value',this.val).text(this.text));
});
$('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');
Why are these two seemingly identical select menus behaving differently? I would like both to act like the static menu (keep 1st value selected) is that possible?
It should also be noted I tried wrapping the disable function in $(document).ready to rule out an issue of the menu not being rendered yet but there was no change. I also tried having two distinct classes with two separate calls to disable the options to make sure its wasn't clashing somehow with no change.
Why are these two seemingly identical select menus behaving differently
This is because the first select
was already part of the document and was parsed. As per the spec here:
The initial state has the first option selected..
and hence the first option was pre-selected. Later on when you disable one option, it doesn't change the selection.
Example 1: You can see that the first select
has disabled
attribute already applied to the first option in markup. The second option gets pre-selected, as compared to the second select
.
<select class="dropMenu">
<option value="1" disabled>First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
In your case of dynamically adding a select
using Javascript, the second select
was created and added to the body
immediately. When this became the part of DOM, there are no options and hence no pre-selection possible. Later when you append options to it, and then disable one of the options, it seems that it gets executed too fast and by the time it is loaded the first option is already disabled and the second one gets pre-selected.
Example 2: Do NOT append the select
immediately to the body
. Append it after you have the options
populated. This time the first option
will be pre-selected despite you changing the disabled
attribute later on.
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val).text(this.text));
});
sel.appendTo('body'); /* <--- append here */
$('.dropMenu option:nth-child(1)').prop('disabled', true);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
Example 3: Add a delay before you disable
an option
. This will give you the intended behaviour of getting the first option
pre-selected because it will have enough time.
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val).text(this.text));
});
setTimeout(disable, 1000); /* <--- give some delay here */
function disable() {
$('.dropMenu option:nth-child(1)').prop('disabled', true);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
Example 4: You can also select one option
explicitly before disabling them.
var arr = [
{val : 1, text: 'One'},
{val : 2, text: 'Two'},
{val : 3, text: 'Three'},
{val : 4, text: 'Four'}
];
var sel = $('<select class="dropMenu">').appendTo('body');
$(arr).each(function () {
sel.append($("<option>").attr('value', this.val).text(this.text));
});
$('.dropMenu option:nth-child(1)').prop('selected', true); /* <-- select explicitly */
$('.dropMenu option:nth-child(1)').prop('disabled', true);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropMenu">
<option value="1">First</option>
<option value="2">Second</option>
<option value="3">Third</option>
<option value="4">fourth</option>
</select>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With