我有一个标准的selt2设置

<div class="form-group">
    <label for="cities">Enter Cities</label>
    <div>
        <select class="form-control cities-tags" multiple="multiple"></select>
    
        <button type="button" id="import-cities" data-bs-toggle="modal" data-bs-target="#importModal">
        <svg>...</svg>
        </button>
    </div>
</div>

应用 Select 2

$(".cities-tags").select2({
    tags: true,
})

我还有一个将逗号分隔值粘贴为文本的模型,它将把它们分割成单独的标记并输入它们.

// #importCitiesBtn is a button in the model to confirm pasting
$('#importCitiesBtn').on('click', function() {
    var importedCities = $('#importCitiesInput').val().split(',');

    importedCities.forEach(function(cityName) {
        if (cityName.trim() == '') {
            return;
        }
        let option = $('.cities-tags').find("option:contains('" + cityName.trim() + "')");

        if (option.length === 0) {
            var newOption = new Option(cityName.trim(), cityName.trim(), true, true);        
            $('.cities-tags').append(newOption).trigger('change');
        } else {
               $('.cities-tags').val(cityName.trim()).trigger('change');
        }
    });
});

Js插入运行得很好,问题是:

当我手动插入城市并移除它们(点击x)时,它们被完全移除(很好)

当我删除js插入的项目时,它从所选项目中删除,但选项仍然存在(错误)

预期行为:当我删除手动或由js添加的项时,它没有踪迹,或者它的选项也从列表中删除.

add logic source

注意:如果您可以编写逻辑将逗号分隔的字符串直接粘贴到SELECT中,并让它自动解析和附加,则需要额外的分数.

推荐答案

手动创建新选项,并将其删除,将删除其选定内容及其选项

假设<select multiple>$(..).select({ tags: true }),则 Select 2允许您输入type个新条目.从所选标签中删除这些条目也会将它们从<select>选项中删除.

当select 2这样做时,它会添加一个额外的属性:data-select2-tag='true' -这就是当你取消 Select 标签时,它如何知道删除option.

因此,当通过代码添加时,您只需添加相同的属性,它将被自动删除-它必须是一个属性,使用$(..).data(是不够的.

当你使用jQuery并且不改变代码的其余部分时,它变成了:

var newOption = new Option(text, value, true, true);
$(newOption).attr("data-select2-tag", "true");

添加新选项,然后在取消 Select 标记时(自动-)删除这些选项的示例:

$('.states').select2({
  tags: true
});

$("#add").click(() => {
  let opt = $(".states option").length;
  var newOption = new Option("opt " + opt, opt, true, true);
  $(newOption).attr("data-select2-tag", "true");
  $('.states').append(newOption).trigger('change');
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/css/select2.min.css" rel="stylesheet" />
<script src="//code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/js/select2.min.js"></script>

<select class="states" multiple>
  <option value="AL">Alabama</option>
  <option value="AK">Alaska</option>
  <option value="AZ">Arizona</option>
</select>

<br/>

<button id="add">
click to add new entry with code
</button>


将逗号分隔的字符串直接粘贴到SELECT并使其自动解析和追加的逻辑

You can listen for the select2:selecting event (note: different versions of use different events), then check e.params.args.data.text - if this has a comma, then split and add multiple new options.

如果一个选项已经存在,则需要将值设置为update以包含现有选项(而不是完全替换select2站点提供的值(根据问题中的代码))

更新代码片段:这里包含NB: This is not working 100%个作为起始点的内容.在输入包含现有选项的逗号分隔值时,如果使用data-selt2-tag添加项目,则似乎会失败.

// Add an exact-equals (can also make this case insensitive)
// https://stackoverflow.com/a/16158932/2181514
$.expr[":"].equals = function(obj, index, meta, stack) {
  return (obj.textContent || obj.innerText || $(obj).text() || "") == meta[3];
};

$('.states').select2({
  tags: true
});

$("#countBtn").click(() => {
  console.log($(".states option").length)
});

$("#addBtn").click(() => {
  let opt = $(".states option").length;
  // this would normally need a check for duplicate, left out here for simplicity
  var newOption = new Option("opt " + opt, opt, true, true);
  $(newOption).data("select2-tag", "true");
  $('.states').append(newOption).trigger('change');
});

$(".states").on("select2:selecting", function(e) {
  if (e.params.args.data.element) return;

  let ddl = $(this);

  let entry = e.params.args.data;
  var opts = entry.text.split(",");

  // only process if more than one, if just one new entry, allow select2 to do its own thing
  if (opts.length > 1) {

    for (var opt of opts) {

      // Check for existing
      let option = ddl.find("option:equals('" + opt.trim() + "')");

      if (option.length === 0) {
        // This specific opt is new
        let newOption = new Option(opt.trim(), opt.trim(), true, true);
        $(newOption).data("select2-tag", "true");
        ddl.append(newOption).trigger('change');
      } else {
        // This opt already exists so update the array of selected values
        // NB: This then *removes* the select2-tag
        let val = ddl.val();
        val.push(opt.trim());
        ddl.val(val).trigger('change');
      }

      // set the return to the current loop, so returns the last entry to select2
      // otherwise it tries to add the original comma-separated list
      e.params.args.data.text = opt.trim();
      e.params.args.data.id = opt.trim();
    }
  }
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/css/select2.min.css" rel="stylesheet" />
<script src="//code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.4/js/select2.min.js"></script>

<select class="states" multiple>
  <option value="AL">Alabama</option>
  <option value="AK">Alaska</option>
  <option value="AZ">Arizona</option>
  <!-- options that are quicker to type, for testing -->
  <option value="X">X</option>
  <option value="Y">Y</option>
</select>

<button id="countBtn">
click after typing new entry
</button>

<button id="addBtn">
click to add new entry with code
</button>

Javascript相关问答推荐

在JavaScript中声明自定义内置元素不起作用

角色 map 集/spritebook动画,用户输入不停止在键上相位器3

成功完成Reducers后不更新状态

如何从Intl.DateTimeFormat中仅获取时区名称?

Prisma具有至少一个值的多对多关系

如何迭代叔父元素的子HTML元素

用JS从平面文件构建树形 struct 的JSON

400 bad request error posting through node-fetch

创建以键值对为有效负载的Redux Reducer时,基于键的类型检测

使用auth.js保护API路由的Next.JS,FETCH()不起作用

如何访问此数组中的值?

FileReader()不能处理Firefox和GiB文件

React:防止useContext重新渲染整个应用程序或在组件之间共享数据而不重新渲染所有组件

Reaction即使在重新呈现后也会在方法内部保留局部值

对不同目录中的Angular material 表列进行排序

如何将对象推送到firestore数组?

扩散运算符未按预期工作,引发语法错误

找不到处于状态的联系人

我想为我的Reaction项目在画布上加载图像/视频,图像正在工作,但视频没有

为什么我的Reaction组件不能使用createBrowserRouter呈现?