禁用第一个选项的动态附加选择菜单会自动选择第二个选项

时间:2015-07-22 14:26:47

标签: javascript jquery html drop-down-menu

我遇到了一个奇怪的案例,据我所知,两件应该表现相同的事情表现得完全不同。

如果我在页面上有两个选择菜单,一个静态菜单在HTML中硬编码,一个在运行时使用JQuery附加到正文。然后我禁用两个选择菜单中的第一个选项。显示时,两个菜单的第一个选项都按预期禁用,但动态附加菜单会自动将值设置为第二个选项,而静态菜单仍然是第一个选中的。

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

为什么这两个看似相同的选择菜单表现不同?我希望两者都像静态菜单一样(保持选择第一个值)是可能的吗?

还应该注意我尝试在$(document).ready中包装disable函数以排除菜单尚未呈现的问题,但没有任何更改。我还试过有两个不同的类,有两个单独的调用来禁用选项,以确保它没有以某种方式发生冲突而没有变化。

5 个答案:

答案 0 :(得分:5)

  

为什么这两个看似相同的选择菜单会表现出来   不同

这是因为第一个select已经是文档的一部分并被解析了。 As per the spec here

  

初始状态选择了第一个选项..

因此第一个选项是预选的。稍后当您禁用一个选项时,它不会更改选择。

示例1 :您可以看到第一个select已将disabled属性应用于标记中的第一个选项。与第二个select相比,第二个选项已预先选定。

&#13;
&#13;
<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>
&#13;
&#13;
&#13;

如果您使用Javascript动态添加select,则会创建第二个select并立即添加到body。当它成为DOM的一部分时,没有选项,因此无法进行预选。稍后当你向它添加选项,然后禁用其中一个选项时,它似乎执行得太快,加载时第一个选项已被禁用,第二个选项被预先选中。

示例2 :请勿立即将select附加到body。填充options后附加它。这一次,即使您稍后更改了option属性,也会预先选择第一个disabled

&#13;
&#13;
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);
&#13;
<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>
&#13;
&#13;
&#13;

示例3 :在disable option之前添加延迟。这将为您提供预先选择的第一个option的预期行为,因为它将有足够的时间。

&#13;
&#13;
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);
}
&#13;
<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>
&#13;
&#13;
&#13;

示例4 :您也可以在禁用它们之前明确选择一个option

&#13;
&#13;
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);
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

尝试在$('.dropMenu option:nth-child(1)').attr('disabled', 'disabled');中设置setInterval,因为您正在创建动态下拉列表,因此执行和创建需要一些时间禁用下拉列表元素jquery将会运行执行。这个问题来了。

Checkout 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>

答案 2 :(得分:0)

默认情况下,如果您已为动态selected的第一个选项添加了选项dropdown,那么它就可以为您完成:

只需看到 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));
});

现在为什么会这样?

对于静态select,该元素已存在于DOM中,然后您使用disabled为第一个option添加jquery,默认情况下首先{ {1}}将保留为option

现在对于动态selected,因为您要添加它select可能是默认情况下不考虑dynamically第一个select,因为它已被禁用!!

即使我觉得这是一种奇怪的行为,但有时我们需要通过追踪和错误来处理这些事情。

答案 3 :(得分:0)

只需手动选择dinamically添加菜单中的第一个选项:

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

jsfiddle here(我借用了你的:P): https://jsfiddle.net/z0dzk5nL/1/

修改 快速更新。 Here您可以找到&#34;选择&#34;的规范。元件。我引用了回答你问题的部分:

  

如果插入节点或删除节点,则会导致选项列表   获取或丢失一个或多个选项元素,或者选项元素   在选项列表中要求重置,然后,如果选择元素   多个属性不存在,用户代理必须先运行   以下列表中适用的一组步骤:

     

如果select元素的显示大小为1,并且没有选项元素   选择元素的选项列表的选择性设置为   true设置列表中第一个选项元素的选择性   树状排序中未被禁用的选项(如果有)为true。

     

如果select元素的选项列表中有两个或更多选项元素   将其选择性设置为true设置所有选择性   最后一个选项元素,其选择性在列表中设置为true   树顺序中的选项为false。

这里有一个小提琴,表明如果你在追加它时预先选择该选项,你可以在不丢失选择的情况下禁用(我使用for循环代替&#34;每个&#34; func完全证明):

jsfiddle.net/xnvbevhm/

(抱歉,我不能发布两个以上的链接,因为我没有足够的声誉:P)

答案 4 :(得分:0)

作为将第一个属性设置为选中的替代方法,使用具有最小时间(即1)的setTimeout似乎可以使事情按预期运行。不过,我仍在研究其原因。

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

Updated fiddle.