2 个 multi select 框相互依赖,第二个 select 文本值未更新

2 multi select boxes dependent of each other, 2nd select text value not updated

我有 2 个这样的多select 盒子

<div class="form-group mb-3">

   <p class="mb-1 font-weight-bold text-muted mt-3 mt-md-0">Addons</p>
   <p class="text-muted font-13">Select multiple Addons</p>
   <select class="form-control select2-multiple" id="multi-select-add-ons" data-toggle="select2"
    multiple="multiple" data-placeholder="Choose ..." style="width: 100%;">

         <optgroup label="Select addons..">
             @foreach ($addons as $a)

               <option value="{{$a->id}}">{{ $a->name }}</option>
             @endforeach
         </optgroup>


    </select>
    <div class="form-group">
         <input id="resultAddons" type="hidden" name="addons_id">
    </div>
</div>


<div class="form-group mb-3">
 <label for="simpleinput">SubAddons</label>
  <select name="" id="subAddons" class="form-control select2-multiple" data-toggle="select2" multiple="multiple" data-placeholder="Choose ..." style="width: 100%;">

      <optgroup label="Select subaddons..">
           <option value="0"></option>
      </optgroup>

 </select>
 <div class="form-group">
  <input id="resultSubAddons" type="hidden" name="sub_addons_id">
 </div>
</div>

好的,所以我在脚本部分使用以下代码从 Api

获取数据
<script>
$('select').change(function () {
    var addons = $("#multi-select-add-ons").val();
    //console.log(addons);
    $('#subAddons').find('option').not(':first').remove();

    addons.map(item => getSubAddonsByAddon(item)) //call subaddons by addon id api
    addons = addons.join(", ");

    document.getElementById('resultAddons').value = addons;
    
  });

  function getSubAddonsByAddon(id) {

    let baseUrl = 'http://localhost.test/add-ons/'
    var xhr = new XMLHttpRequest();
    xhr.open("GET", `${baseUrl}show/${id}/sub-add-ons`, true);
    xhr.setRequestHeader("Content-Type", "application/json");
        
    xhr.onreadystatechange = function() { // Call a function when the state changes.
        if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
          let data = JSON.parse(this.response);

          let complexArr = [data][0].data;

          complexArr.forEach(element => {
           // console.log(element.name);

            getSubAddonIdAndName(element);
          });
          
        } 
    }
    xhr.send();

  }
  let subAddonID, name;
  
  function getSubAddonIdAndName(data) {
    
    this.subAddonID = data.id;
    this.name = data.name;

    $("#subAddons").append($('<option>', {
        value: data.id ,
        text: data.name
    })); 

  }
</script>

这是它的样子,代码工作正常,第二个 select(子插件)下拉列表根据插件的 selection 更新,名称如何不显示在select 框文本字段

在 select 从第二个 select 框输入一个值后,该值不像第一个 select 框的值那样显示

它返回到“选择...”而不是像第一个框那样显示名称

如果您正在为多个 select 使用一个库,会发生什么情况是该库在您的输入上运行一个处理方法来处理它第一次拥有的任何数据,如果您向它附加更多数据,您需要重新调用那个库的handle方法。

要在 select-box 文本字段中显示选项,您可以在 select2 中添加新选项时添加 selected: true 行,然后 $("#subAddons").trigger("change") 更新您的 select2 插件 .

然后,您的第二个问题是因为 $('select').change(function () { 行,因为您在第二个 select-box 中更改选项时将 select 用作 select 左右此事件被调用并且选项再次更新。所以,为了避免这种情况,只需使用更具体的 select 或即:select#multi-select-add-ons

演示代码 :

$("#multi-select-add-ons ,#subAddons").select2()
//be more specific here
$('select#multi-select-add-ons').change(function() {
  var addons = $("#multi-select-add-ons").val();
  $('#subAddons').find('option:not(:first)').remove();
  addons.map(item => getSubAddonsByAddon(item))
  addons = addons.join(", ");
  document.getElementById('resultAddons').value = addons;

});

function getSubAddonsByAddon(id) {

  /*let baseUrl = 'http://localhost.test/add-ons/'
  var xhr = new XMLHttpRequest();
  xhr.open("GET", `${baseUrl}show/${id}/sub-add-ons`, true);
  xhr.setRequestHeader("Content-Type", "application/json");

  xhr.onreadystatechange = function() { // Call a function when the state changes.
    if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
      let data = JSON.parse(this.response);*/
  //suppose this is data came from server
  let data = [{
    "data": [{
      "id": 1,
      "name": "abc"
    }, {
      "id": 2,
      "name": "ace"
    }]
  }]
  let complexArr = data[0].data;
  complexArr.forEach(element => {
    getSubAddonIdAndName(element);
  });
  $("#subAddons").trigger("change") //after appending options refresh select2

  /*}
  }
  xhr.send();*/

}
let subAddonID, name;

function getSubAddonIdAndName(data) {

  this.subAddonID = data.id;
  this.name = data.name;

  $("#subAddons").append($('<option>', {
    value: data.id,
    text: data.name,
    selected: true //add this
  }));

}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" />
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.full.min.js"></script>


<div class="form-group mb-3">

  <p class="mb-1 font-weight-bold text-muted mt-3 mt-md-0">Addons</p>
  <p class="text-muted font-13">Select multiple Addons</p>
  <select class="form-control select2-multiple" id="multi-select-add-ons" data-toggle="select2" multiple="multiple" data-placeholder="Choose ..." style="width: 100%;">

    <optgroup label="Select addons..">


      <option value="1">A</option>
      <option value="2">A2</option>
      <option value="3">A3</option>

    </optgroup>


  </select>
  <div class="form-group">
    <input id="resultAddons" type="hidden" name="addons_id">
  </div>
</div>


<div class="form-group mb-3">
  <label for="simpleinput">SubAddons</label>
  <select name="" id="subAddons" class="form-control select2-multiple" data-toggle="select2" multiple="multiple" data-placeholder="Choose ..." style="width: 100%;">

    <optgroup label="Select subaddons..">
      <option value="0"></option>
    </optgroup>

  </select>
  <div class="form-group">
    <input id="resultSubAddons" type="hidden" name="sub_addons_id">
  </div>
</div>