首页 > 解决方案 > 2个相互依赖的多选框,第二个选择文本值未更新

问题描述

我有 2 个这样的多选框

<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>

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

在此处输入图像描述

从第二个选择框中选择一个值后,该值不像第一个选择框值那样显示

在此处输入图像描述

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

标签: javascriptjquerylaravelmulti-select

解决方案


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

然后,您的第二个问题是因为$('select').change(function () {您已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>


推荐阅读