select2 onchange 事件只能触发一次

34

我在使用jQuery的Select2时遇到了问题。

当页面加载时,如果我点击搜索结果,它会选择并触发onchange事件,但只有第一次有效。

如果我再搜索一次,就不会有反应。

这是我的代码(它是基于Ajax的搜索):

jQuery('#search_code').select2({
    'width': '600px',
    'tokenSeparators': [',', ' '],
    'closeOnSelect': false,
    'placeholder': 'scan or type a SKU or product or ESN',
    'minimumInputLength': 1,
    'ajax': {
        'url': 'lookProduct',
        'dataType': 'json',
        'type': 'POST',
        'data': function (term, page) {
            return {
                barcode: term,
                page_limit: 3,
                page: page
            };
        },
        'results': function (data, page) {
            return {
                results: data
            };
        }
    }
}).on('change', function (e) {
    var str = $("#s2id_search_code .select2-choice span").text();

    DOSelectAjaxProd(this.value, str);
    //this.value
}).on('select', function (e) {
    console.log("select");

});

你在调试器中尝试过吗?当第一个onchange事件发生时,是否出现任何错误消息? - Lochemage
尝试使用以下代码 $(document).on('change', 'span#search_code', function(... 并检查其是否有效。如果 #search_code 是 div 的 id,则将 span 替换为 div,或者根据 "element" 的类型替换为 "element"。 - Optimus Prime
是的,这只是个误报。实际上我选择了同一个元素,所以在这种情况下不会触发变更事件。 - PartySoft
哦,但是有一个问题... onchange 不会在相同的索引上触发...因此,如果您有一个 ajax 选择器,其中有两个结果,并且您选择了索引 1...然后再次搜索...并且您有 X 个结果,并再次选择索引 1...内容可能不同,但是索引相同...因此,我必须每次都强制执行 onchange。我该怎么做? - PartySoft
我找到了一个与我的问题类似的帖子,但是如何修改我的代码呢?https://dev59.com/aWQo5IYBdhLWcg3wbe5K - PartySoft
8个回答

44

这是我正在使用的:

$("#search_code").live('change', function(){
  alert(this.value)
});

对于最新版本的jQuery用户,这个应该可以工作:

$(document.body).on("change","#search_code",function(){
 alert(this.value);
});

喜欢第二个建议。简洁、短小和实用。 - Pablo Contreras

19
自从版本 4.0.0起,像 select2-selecting 这样的事件将不再使用,它们被重命名如下:

  • select2-close 现在是 select2:close
  • select2-open 现在是 select2:open
  • select2-opening 现在是 select2:opening
  • select2-selecting 现在是 select2:selecting
  • select2-removed 现在是 select2:removed
  • select2-removing 现在是 select2:unselecting

参考:https://select2.org/programmatic-control/events

(function($){
  $('.select2').select2();
  
  $('.select2').on('select2:selecting', function(e) {
    console.log('Selecting: ' , e.params.args.data);
  });
})(jQuery);
body{
  font-family: sans-serif;
}

.select2{
  width: 100%;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.full.min.js"></script>

<select class="select2" multiple="multiple">
  <option value="1">Option 1</option>
  <option value="2">Option 2</option>
  <option value="3">Option 3</option>
  <option value="4">Option 4</option>
  <option value="5">Option 5</option>
  <option value="6">Option 6</option>
  <option value="7">Option 7</option>
</select>


18

显然,在使用数据时,如果已存在选择,则不会触发更改事件。我最终手动更新了选择的数据以解决这个问题。

$("#search_code").on("select2-selecting", function(e) {
    $("#search_code").select2("data",e.choice);
});

我知道这可能有点晚,但希望这个答案能够节省其他人的时间。


很好...我为动态下拉菜单修改了如下代码:$(document).on('select2-selecting','#search_code',function(e){ $('#search_code').select2('data', e.choice); }); - nikhil
1
我也注意到了同样的行为。如果一个项目已经被选中,当选择另一个项目时,更改事件不会触发。请看@cpugourou的答案。确保该项目具有唯一的ID可以使更改事件触发。 - Keith Sirmons
我不理解你的引言评论... 你能更简洁明了吗? - Stephane

9
$('#search_code').select2({
.
.
.
.
}).on("change", function (e) {
      var str = $("#s2id_search_code .select2-choice span").text();
      DOSelectAjaxProd(e.val, str);
});

1
这个回答如何解决问题?与原始问题有什么不同之处? - Teepeemm
在我看来,它看起来完全一样。你声称自己回答了OP的问题。这怎么回答问题呢?出了什么问题?现在又是什么问题? - Teepeemm

7
这是由于项目id相同所致。 只有在选择时检测到不同的项目id,on change才会触发。
所以您有两个选项: 第一是确保从ajax检索数据时每个项目都具有唯一的id。
第二是在所选项目的formatSelection处触发一个随机数。
function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

.

formatSelection: function(item) {item.id =getRandomInt(1,200)}

2
我的select2元素没有触发onchange事件,因为下拉列表只提供了一个值,这使得无法更改该值。
由于值没有改变,因此没有触发任何事件,处理程序也无法执行。
然后我添加了另一个处理程序来清除该值,使用select2-open处理程序在onchange处理程序之前被执行。
现在源代码看起来像这样:
el.on("select2-open", function(e) {
    $(this).val('');
});
el.on('change', function() {
    ...
});

第一个处理程序清除该值,即使选择相同的值也允许第二个处理程序启动。


2

将您的.on监听器设置为检查特定的select2事件。 “change”事件与通常相同,但其他事件是特定于select2控件的,因此如下:

  • change(更改)
  • select2-opening(打开)
  • select2-open(已打开)
  • select2-close(关闭)
  • select2-highlight(高亮)
  • select2-selecting(选择)
  • select2-removed(已删除)
  • select2-loaded(已加载)
  • select2-focus(聚焦)

这些名称不言自明。例如,select2-focus在您将焦点放到控件上时激活。


0
如果你正在使用 Stimulus JS,则在 connect 方法中编写:
$("#idOfSelect2").on('change', function(){ //write your logic here})

如果您正在使用原生JS,则可以在页面加载时调用一个函数,并执行与上述相同的操作:

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接