由于某些原因,向SELECT标记添加选项不会选择selected ='selected'属性选项,而是选择列表中的下一个选项。
请参阅上面的jfiddle。
<select id="category">
<option value='1'>Categroy 1</option>
<option value='2'>Categroy 2</option>
<option value='3'>Categroy 3</option>
</select>
<select id="sub-category">
<option value='1' data-parentid='1'>Car1</option>
<option value='2' data-parentid='1'>Car2</option>
<option selected='selected' value='3' data-parentid='1'>Car3</option>
<option value='4' data-parentid='1'>Car4</option>
<option value='5' data-parentid='1'>Car5</option>
<option value='6' data-parentid='2'>Car6</option>
<option value='7' data-parentid='2'>Car7</option>
<option value='8' data-parentid='2'>Car8</option>
<option value='9' data-parentid='3'>Car9</option>
<option value='10' data-parentid='3'>Car10</option>
<option value='11' data-parentid='3'>Car11</option>
<option value='12' data-parentid='3'>Car12</option>
</select>
$(document).ready(function(){
var allsuboptions = $('#sub-category option').remove();
var selectedOptions = allsuboptions.filter(function () {
return $(this).data('parentid').toString() === $('#category').val().toString();
});
selectedOptions.appendTo('#sub-category');
});
在上面的示例中,应该选择Car3,但是在将选项附加到选择后选择Car4。
答案 0 :(得分:3)
这是一个棘手(有趣)的问题。
如果您在不同浏览器上测试小提琴,您会看到所选值发生变化:Chrome(Car4),IE(Car3),Firefox(Car5)。所以我对你的小提琴做了一点改变,以“证明一个理论”。您可以在此链接上看到更改:http://jsfiddle.net/j3oh6s3a/1/。我只在过滤器循环中添加了一个日志,因此我可以在每次迭代中看到所选元素:
if ($(this).is(":selected")) { console.log("Selected value = " + $(this).val()) };
现在发生这种情况(或者至少是我的理论):从列表中删除所选元素后,每个浏览器都会继续,但认为足以确定所选选项。在这种情况下,每个浏览器将以不同的方式进行:
由于所选选项已被删除, Chrome 会自动(默认情况下)选择列表中剩余的option
(Car4)。将此选项发送到新列表时,会自动选择该选项,因为它比先前选择的选项更新。日志是:3,4。
Internet Explorer 不执行任何操作,并以相同的方式复制每个元素,而不关心它们是否被选中。原始选定值将是最终选定值(Car3)。日志是:3。
Firefox 将像Chrome一样继续,但每次从列表中删除所选元素时,将选择其余元素的第一个选项。日志是:3,4,5,6,7,8,9,10,11,12;但是当列表中插入的最后一个选项是5时,它将是所选的选项。
我稍后会查看是否可以找到任何信息来获取此信息,但它必须是明天,因为它有点晚了。
答案 1 :(得分:3)
jQuery .remove和.append内部使用.removeChild和.appendChild方法删除/插入子元素。
当您使用removeChild然后appendChild重新添加选项时,将保留属性,但不保留元素的属性。您可以在此处详细了解 .prop() vs .attr() 。
总之,属性是HTML中定义的初始值,它们被解析为由浏览器设置为Element的属性,但是设置属性并不能保证设置属性。
$(function() {
var categoryDD = document.getElementById('category');
var removedOptions = remove.call(categoryDD.options);
add.call(categoryDD, removedOptions);
});
function add(options) { //add all options
for (var i = 0; i < options.length; i++) {
this.appendChild(options[i]);
}
}
function remove() { //removes all options
var el, returnOpt = [];
while (this.length) {
el = this[0];
returnOpt.push(el.parentNode.removeChild(el));
}
return returnOpt;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<select id="category">
<option value='1'>Categroy 1</option>
<option value='2' selected="selected">Categroy 2</option>
<option value='3'>Categroy 3</option>
<option value='4'>Categroy 4</option>
<option value='5'>Categroy 5</option>
<option value='6'>Categroy 6</option>
</select>
在测试上面的代码片段时,IE 10和FF产生了相同的结果,即从下拉列表中选择最后一个选项,但是Chrome似乎有问题,因为它始终从原始选择中选择下一个选项。 IE 10和FF的结果对于“不维持状态”有点意义,但Chrome行为似乎是一个错误。
以上是基于我的测试用例的理论,但是我找不到一个说明相同的合法参考。
无论如何,请尝试以下解决方案以获得一致的输出。
解决方案1:仅删除不等于的选项到parentId。
$('#sub-category option').filter(function () {
return $(this).data('parentid').toString() !== $('#category').val().toString();
}).remove();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<select id="category">
<option value='1'>Categroy 1</option>
<option value='2'>Categroy 2</option>
<option value='3'>Categroy 3</option>
</select>
<select id="sub-category">
<option value='1' data-parentid='1'>Car1</option>
<option value='2' data-parentid='1'>Car2</option>
<option selected='selected' value='3' data-parentid='1'>Car3</option>
<option value='4' data-parentid='1'>Car4</option>
<option value='5' data-parentid='1'>Car5</option>
<option value='6' data-parentid='2'>Car6</option>
<option value='7' data-parentid='2'>Car7</option>
<option value='8' data-parentid='2'>Car8</option>
<option value='9' data-parentid='3'>Car9</option>
<option value='10' data-parentid='3'>Car10</option>
<option value='11' data-parentid='3'>Car11</option>
<option value='12' data-parentid='3'>Car12</option>
</select>
解决方案2:[基于您的原始答案] 解决方案很简单,只需在删除选项之前获取选择值,并在使用.append之后设置选择。
var $subcategory = $('#sub-category');
var selectedOption = $subcategory.val();
var allsuboptions = $subcategory.find('option').remove();
var selectedOptions = allsuboptions.filter(function() {
return $(this).data('parentid').toString() === $('#category').val().toString();
});
selectedOptions.appendTo('#sub-category');
$subcategory.val(selectedOption);
<select id="category">
<option value='1'>Categroy 1</option>
<option value='2'>Categroy 2</option>
<option value='3'>Categroy 3</option>
</select>
<select id="sub-category">
<option value='1' data-parentid='1'>Car1</option>
<option value='2' data-parentid='1'>Car2</option>
<option selected='selected' value='3' data-parentid='1'>Car3</option>
<option value='4' data-parentid='1'>Car4</option>
<option value='5' data-parentid='1'>Car5</option>
<option value='6' data-parentid='2'>Car6</option>
<option value='7' data-parentid='2'>Car7</option>
<option value='8' data-parentid='2'>Car8</option>
<option value='9' data-parentid='3'>Car9</option>
<option value='10' data-parentid='3'>Car10</option>
<option value='11' data-parentid='3'>Car11</option>
<option value='12' data-parentid='3'>Car12</option>
</select>
答案 2 :(得分:2)
您未看到的是“已选择”属性与“已选择”属性之间的区别。 如果你把它放在你的代码的末尾,你可以看到它:
// Attribute
console.log( $("#sub-category").find("[selected]").val() );
// Property
console.log( $("#sub-category").find(":selected").val() );
您的值为“3”的选项具有所选属性,但不具有属性,而值为“4”的选项则相反。
每当您在select中添加选项时,您必须重新选择所需的选项:
$("#sub-category").find("[selected]").prop("selected", true);
答案 3 :(得分:2)
Firefox选择最后一个元素。这种行为可能是正确和可解释的。为了理解,请记住以下几点:
预期行为(Firefox)
如示例中所示,从select元素中删除所有选项的工作方式如下:
这将重复,直到所有选项从DOM移动到内存。此时,选项将具有以下属性:
// allsuboptions.each(function() { console.log(this.value, this.selected); });
value: 1, selected: false
value: 2, selected: false
value: 3, selected: true
value: 4, selected: true
...
value: 12, selected: true
selected = true
有3个选项。将选项添加回select元素时,浏览器会将最后选择的元素设置为所选元素。
Internet Explorer和Chrome
虽然逐个删除选项,但这两个浏览器不会立即更新所选元素(它们可能等待JavaScript执行完成)。这会导致以下差异:
当删除当前选定的选项时,Internet Explorer不会立即选择下一个选项。因此,删除的选项仅包含一个选定元素。
Chrome似乎立即在删除当前选定的选项时选择下一个选项,但它只执行一次。因此,删除的选项包含两个选定的元素。
为了证明关于立即和延期更新的观点,这里有一个小提琴包含:
http://jsfiddle.net/salman/j3oh6s3a/9/
<强>解决方案强>
正如其他答案中所建议的那样,正确的解决方法是在删除选项之前使用引用当前所选选项的变量。类似的东西:
var $selectedOption = $("#sub-category option").filter(function() {
return this.selected;
});
重新插入选项后,您可以检查是否已添加该元素并再次选择它:
if ($selectedOption.parent().length) {
$selectedOption.prop("selected", true);
}
// or
$("#sub-category option").filter($selectedOption).prop("selected", true);
答案 4 :(得分:0)
您的脚本正在执行您创建的操作。
选择car4的原因是因为
<option selected='selected' value='3' data-parentid='1'>Car3</option>
最初选择了,然后您appending
parentid ='1'到导致car4成为新选择的值。
这个脚本的目的是什么?