Dynamically added selection menu with the 1st option disabled. Automatically selects the second option.

I ended up in a strange case where, as far as I know, two things that should act the same way behave in a completely different way.

If I have two selection menus per page, one static menu is hardcoded in HTML and one is added to the body at runtime using jQuery. Then I turn off the first option in both selection menus. When both menus are displayed, their first parameters are disabled as expected, however a dynamically added menu automatically sets the value for the second parameter, while the static menu still has the first one 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 do these two seemingly identical selection menus behave differently? I would like both actions, like a static menu (to keep the 1st value selected), perhaps?

It should also be noted that I tried to wrap the disable function in $ (document) .ready to eliminate the problem with showing the menu, but there were no changes. I also tried to have two different classes with two separate calls to disable the parameters, to make sure that it did not come across somehow without any changes.

+6
source share
5 answers

Why do these two seemingly identical selection menus behave differently

This is because the first select already part of the document and was parsed. According to the specification here :

In the initial state, the first option is selected.

and therefore, the first option has been pre-selected. Later, when you turn off one parameter, it does not change the selection.

Example 1 You can see that the first select has a disabled attribute already applied to the first parameter in the markup. The second option is pre-selected, 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 select using Javascript, a second select was created and immediately added to the body . When it became part of the DOM, there are no options and therefore it is impossible to foresee a choice. Later, when you add parameters to it, and then turn off one of the parameters, it seems that it is running too fast, and by the time it is loaded, the first parameter is already disabled, and the second is selected in advance.

Example 2 Do not add select directly to body . Add it after filling in the options . This time, the first option will be preselected, although later you will change the disabled attribute.

 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 a option . This will give you the expected behavior of getting the first option preselected, 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 explicitly select one option 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> 
+5
source

try setting $('.dropMenu option:nth-child(1)').attr('disabled', 'disabled'); in setInterval , because you are creating a dynamic drop-down menu, so it will take some time to execute and create it, in the meantime you will display a dropdown to disable jquery. therefore the problem arises.

Order code snippet

 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(function() { $('.dropMenu option:nth-child(1)').attr('disabled', 'disabled'); }, 1); 
 <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> 
+1
source

Well, by default, if you provided the selected option to the first option of your dynamic dropdown , then this would be done for you:

Just have a look DEMO :

 $(arr).each(function(key,value) { if(key==0) sel.append($("<option>").attr('value',this.val).text(this.text).attr('selected',true)); else sel.append($("<option>").attr('value',this.val).text(this.text)); }); 

Now why is this happening?

For a static select element is already present in the DOM , and then you add disabled for the first option using jquery and by default the option will first be stored as selected already.

Now for dynamic select , since you are adding it dynamically , it may not consider select first option by default, since it is disabled !!

Even I feel it as strange behavior, but sometimes I need to take care of these things in the wake and error.

0
source

Just select the first option in the dynamically added menu:

 $('.dropMenu option:nth-child(1)') .attr('disabled', 'disabled') .attr('selected', 'selected'); 

jsfiddle here (I borrowed your: P): https://jsfiddle.net/z0dzk5nL/1/

EDIT Quick update. Here you can find the specification for the select element. I quoted the part that answers your question:

If nodes are inserted or nodes are removed, resulting in a list of options for getting or losing one or more option elements, or if an option element is requested to be reset in the list of options, then if the select element does not have a multiple attribute, the user agent must start the first applicable set of steps from the following list:

If the display size of the selection element is 1 and there are no elements in it, the list of elements in the list of elements of the selection has its selected true. Set the selected element of the first element in the list to the parameters in a tree order that are not disabled, if any, to true.

If two or more option items in the list of select items, set their choice to true. Select the last selected option element with its value set to true in the tree of options in the list of options false.

And here is a fiddle to show that if you pre-select an option when adding it, you can turn it off without losing the selection (I used the for loop instead of the "each" function to demonstrate this):

jsfiddle.net/xnvbevhm/

(sorry, I can not post more than two links, because I do not have enough reputation: P)

0
source

As an alternative to setting the first attribute selected, using setTimeout with minimal time (i.e. 1) seems to behave as expected. I am still studying the reason for this.

 setTimeout(function() { $('.dropMenu option:nth-child(1)').attr('disabled', 'disabled'); }, 1); 

Updated script .

0
source

All Articles