基于数组项的Select2选择顺序

3
我正在尝试根据一个数组设置Select2中所选项目的顺序。
已经有一个简单的解决方案,可以按照下拉菜单中点击的顺序附加项目(请参见此讨论中2017-10-26 2rba的答案)。
        $("#selectCriteria").on("select2:select", function (evt) {
          var element = evt.params.data.element;
          var $element = $(element);
          $element.detach();
          $(this).append($element);
          $(this).trigger("change");
    });

我想要做的是模仿这种行为,但是当传递一个选定项目的数组而不是手动在列表中点击它们时。我尝试了以下命令:
displayed_items = ["b", "c", "a"];  
$('#selectCriteria').val(displayed_items).trigger('change'); 

但是顺序没有保留。我尝试逐个元素循环执行命令,但每次新的调用都会覆盖上一个元素:

 $('#selectCriteria').val("b").trigger('change'); 
 $('#selectCriteria').val("c").trigger('change'); 
 $('#selectCriteria').val("a").trigger('change'); 

我看到了两种可能的解决方案,但缺乏背景知识来使它们起作用:

  1. 如何调整上面的迭代,以便覆盖先前添加的值?
  2. 我如何将这个fiddle(来自vol7ron在github上的帖子)中展示的方法合并进来,它几乎做到了我所要求的(即切换打开/关闭.data('preserved-order',selected))?由于它使用了JSX,我不确定如何在我的纯JS/jQuery脚本中重用该脚本。
2个回答

6

这是需要翻译的内容:

EDIT:

这不是最好的解决方案,但它能完成工作。

您需要调用initSelect函数,并将一个value数组作为参数传递进去。我在代码中留下了一些注释。

here you go

displayed_items = $('#selected_items').val().split(',');
    
function selectItem(target, id) { // refactored this a bit, don't pay attention to this being a function
  var option = $(target).children('[value='+id+']');
  option.detach();
  $(target).append(option).change();
} 

function customPreSelect() {
  let items = $('#selected_items').val().split(',');
  $("select").val('').change();
  initSelect(items);
}

function initSelect(items) { // pre-select items
  items.forEach(item => { // iterate through array of items that need to be pre-selected
    let value = $('select option[value='+item+']').text(); // get items inner text
    $('select option[value='+item+']').remove(); // remove current item from DOM
    $('select').append(new Option(value, item, true, true)); // append it, making it selected by default
  });
}

$('select').select2();
$('select').on('select2:select', function(e){
  selectItem(e.target, e.params.data.id);
});

initSelect(displayed_items); // call init
select {
  width: 50%;
}

.container {
  display: flex;
  flex-direction: column;
}

.control-group {
  padding-bottom: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/js/select2.min.js"></script>

<div class="container">

  <p>Provide comma separated items to be pre selected and click the button</p>
  <div class="control-group">
    <input id="selected_items" value="b,c,a"/>
    <button onclick="customPreSelect()">Init</button>
  </div>

  <select multiple="multiple">
    <option value="a">A</option>
    <option value="b" >B</option>
    <option value="c">C</option>
    <option value="d">D</option>
  </select>
</div>


谢谢,不过这似乎更像是我问题中第一个片段的重新实现。你的版本是否也可以在传递一个数组时正常工作,例如使用命令$('#select').val(myArray).trigger('change');?这就是我想要实现的。你能否在你的示例中友好地说明如何使用预定数组(例如["b","a","d"])来实现这一点? - undefined
1
啊哈,抱歉,我看错了。给我一分钟,我会更新答案的。 - undefined
还添加了一个小的游乐场控件,使其更具说明性 - undefined
非常感谢!它确实完美地完成了工作。几乎是即插即用的,我只需要稍微调整一下[value='+item+']')[value="'+item+'"]'),因为我的一些名称中有一些更复杂的空格。但除此之外无可挑剔! - undefined
很高兴能帮忙。对于缺少的引号表示抱歉。 - undefined

0
这将保留select2选项的属性(例如用于工具提示的标题):
function initSelect(items) {
    items.forEach(item => {
        var option = $('#selectCriteria').children('[value="' + item + '"]');
        option[0].selected = true;
        option.detach();
        $('#selectCriteria').append(option).change();
    })
}

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