我没想到,但是以下测试在克隆值检查上失败了:
test("clone should retain values of select", function() {
var select = $("<select>").append($("<option>")
.val("1"))
.append($("<option>")
.val("2"));
$(select).val("2");
equals($(select).find("option:selected").val(), "2", "expect 2");
var clone = $(select).clone();
equals($(clone).find("option:selected").val(), "2", "expect 2");
});
这是对的吗?
答案 0 :(得分:69)
经过进一步研究后,我在JQuery bug跟踪系统中找到了这张票,它解释了这个bug并提供了解决方法。显然,克隆选择值太昂贵,所以他们不会修复它。
https://bugs.jquery.com/ticket/1294
我对克隆方法的使用是在通用方法中,任何可能克隆的东西,所以我不确定何时或是否会有一个选择来设置值。所以我添加了以下内容:
var selects = $(cloneSourceId).find("select");
$(selects).each(function(i) {
var select = this;
$(clone).find("select").eq(i).val($(select).val());
});
答案 1 :(得分:27)
这是jQuery克隆方法的固定版本:
https://github.com/spencertipping/jquery.fix.clone
// Textarea and select clone() bug workaround | Spencer Tipping
// Licensed under the terms of the MIT source code license
// Motivation.
// jQuery's clone() method works in most cases, but it fails to copy the value of textareas and select elements. This patch replaces jQuery's clone() method with a wrapper that fills in the
// values after the fact.
// An interesting error case submitted by Piotr Przybył: If two <select> options had the same value, the clone() method would select the wrong one in the cloned box. The fix, suggested by Piotr
// and implemented here, is to use the selectedIndex property on the <select> box itself rather than relying on jQuery's value-based val().
(function (original) {
jQuery.fn.clone = function () {
var result = original.apply(this, arguments),
my_textareas = this.find('textarea').add(this.filter('textarea')),
result_textareas = result.find('textarea').add(result.filter('textarea')),
my_selects = this.find('select').add(this.filter('select')),
result_selects = result.find('select').add(result.filter('select'));
for (var i = 0, l = my_textareas.length; i < l; ++i) $(result_textareas[i]).val($(my_textareas[i]).val());
for (var i = 0, l = my_selects.length; i < l; ++i) result_selects[i].selectedIndex = my_selects[i].selectedIndex;
return result;
};
}) (jQuery.fn.clone);
答案 2 :(得分:8)
从Chief7的回答中做了一个插件:
(function($,undefined) {
$.fn.cloneSelects = function(withDataAndEvents, deepWithDataAndEvents) {
var $clone = this.clone(withDataAndEvents, deepWithDataAndEvents);
var $origSelects = $('select', this);
var $clonedSelects = $('select', $clone);
$origSelects.each(function(i) {
$clonedSelects.eq(i).val($(this).val());
});
return $clone;
}
})(jQuery);
仅对其进行了简要测试,但似乎有效。
答案 3 :(得分:3)
我的方法略有不同。
我没有在克隆过程中修改选择,而只是在select
页上查看每个change
事件,然后,如果值已更改,我需要添加所需的selected
属性已选择<option>
,因此它变为<option selected="selected">
。由于选择现已标记在<option>
的标记中,因此当您选择.clone()
时,它将会被传递。
您需要的唯一代码:
//when ANY select on page changes its value
$(document).on("change", "select", function(){
var val = $(this).val(); //get new value
//find selected option
$("option", this).removeAttr("selected").filter(function(){
return $(this).attr("value") == val;
}).first().attr("selected", "selected"); //add selected attribute to selected option
});
现在,您可以按照您想要的方式复制选择,并且还会复制它的值。
$("#my-select").clone(); //will have selected value copied
我认为此解决方案较少自定义因此,如果您稍后修改某些内容,则无需担心代码是否会中断。
如果您不希望将其应用于页面上的每个选择,您可以在第一行更改选择器,如:
$(document).on("change", "select.select-to-watch", function(){
答案 4 :(得分:2)
是。这是because'select'DOM节点的'selected'属性与选项的'selected'属性不同。 jQuery不会以任何方式修改选项的属性。
请改为尝试:
$('option', select).get(1).setAttribute('selected', 'selected');
// starting from 0 ^
如果你真的对val函数的工作原理感兴趣,你可能想要检查
alert($.fn.val)
答案 5 :(得分:2)
克隆<select>
不复制value=
上的<option>
属性。所以Mark的插件并不适用于所有情况。
要修复,请在克隆<select>
值之前执行:
var $origOpts = $('option', this);
var $clonedOpts = $('option', $clone);
$origOpts.each(function(i) {
$clonedOpts.eq(i).val($(this).val());
});
克隆选择<select>
选项的另一种方法,在jQuery 1.6.1 + ...
// instead of:
$clonedSelects.eq(i).val($(this).val());
// use this:
$clonedSelects.eq(i).prop('selectedIndex', $(this).prop('selectedIndex'));
后者允许您在设置<option>
之后设置selectedIndex
值。
答案 6 :(得分:2)
简化chief7的回答:
var cloned_form = original_form.clone()
original_form.find('select').each(function(i) {
cloned_form.find('select').eq(i).val($(this).val())
})
再次,这是jQuery票证:http://bugs.jquery.com/ticket/1294
答案 7 :(得分:0)
如果您只需要select的值,序列化表单或类似的东西,这对我有用:
$clonedForm.find('theselect').val($origForm.find('theselect').val());
答案 8 :(得分:0)
在尝试了不同的解决方案1小时后,我确实创建了这个简单的解决方案
$clonedItem.find('select option').removeAttr('selected');
$clonedItem.find('select option[value="' + $originaItem.find('select').val() + '"]').attr('selected', 'true');
答案 9 :(得分:0)
@ pie6k显示了一个好主意。
它解决了我的问题。我把它改成一点点:
$(document).on("change", "select", function(){
var val = $(this).val();
$(this).find("option[value=" + val + "]").attr("selected",true);
});
答案 10 :(得分:0)
$(document).on("change", "select", function(){
original = $("#original");
clone = $(original.clone());
clone.find("select").val(original.find("select").val());
});
答案 11 :(得分:0)
只报告回来。由于某些不为人知的原因,即使这是我测试的第一件事,而且我也没有更改代码,现在是
$("#selectTipoIntervencion1").val($("#selectTipoIntervencion0").val());
方法正在起作用。我不知道为什么或一旦更改某些内容它是否会再次停止工作,但是我现在就继续讨论。谢谢大家的帮助!