Select2 多选选项以在另一个多选中显示选项

Select2 multiselect options to display options in another multiselect

我刚刚将我的一个 multiselect 切换为 select2,因为我之前的复选框 multiselect 与我的新页面模板 CSS 不兼容并且看起来非常不合适。

第一个 multiselect(现在是 select2),用户可以 select 他们的大量选项和下面的第二个 multiselect将填充与第一个已经 selected 相关的选项,并且该字段是只读的。这以前工作得很好,但现在不再这样做了。

这是我正在使用的代码。 select2hazards 的选项是从按预期工作的数据库中提取的。

$(document).ready(function() {
    $('#hazards').select2();
});

window.addEventListener('DOMContentLoaded', () => {
  let hprops = document.querySelector('#hp_codes')
  document.querySelector('#hazards').addEventListener('change', e => {
    let options = e.target.options;
    let hazards = [];
    for (var i = 0, l = options.length; i < l; i++) {
      if (options[i].selected) {
        hazards.push(options[i].value);
      }
    }

    hprops.innerHTML = '';
    hprops.setAttribute('disabled', true); // disable until we get the data in there
    // ajax to get actual data ...
    let results = []
    if (hazards.includes("H200") || hazards.includes("H201")) results.push('HP1')
    if (hazards.includes('H300') || hazards.includes("H301")) results.push('HP6')
    if (hazards.includes('H400') || hazards.includes("H410")) results.push('HP14')

    results.forEach(r => hprops.innerHTML += `<option selected value='${r}'>${r}</option?`)
    hprops.removeAttribute('disabled');

  })
})

// array_unique compressed:
    function array_unique(d){var c="",b={},e="";var a=function(h,g){var f="";for(f in g){if(g.hasOwnProperty(f)){if((g[f]+"")===(h+"")){return f}}}return false};for(c in d){if(d.hasOwnProperty(c)){e=d[c];if(false===a(e,b)){b[c]=e}}}return b}


var optionValues = [];
$('#hp_codes').each(function() {
  optionValues.push($(this).val());
  $(this).remove(); // remove the option element
});

var cleanedArray = array_unique(optionValues); // clean the array

// let's go to paint the new options
for(var i in cleanedArray) {
  var opt = $('<option/>')
                .attr('value', cleanedArray[i]) // note that the value is equal than the text
                .text(cleanedArray[i]);
  $('#hp_codes').append(opt);
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>

          <div class="row form-group">
            <div class="col-sm-4">
              <label class="control-label modal-label">Hazard Statements: </label>
              <span class="text-danger">*</span> </div>
            <div class="mb-3 col-sm-8">
              <select class="form-control select2" data-toggle="select2" id="hazards" name="hazards" multiple required>           
              <option value="H200">H200</option>
              <option value="H201">H201</option>              
              <option value="H300">H300</option>
              <option value="H301">H301</option>              
              <option value="H400">H400</option>
              <option value="H410">H410</option>              
              </select>             
            </div>
          </div>
          </br>
          <div class="row form-group">
            <div class="col-sm-4">
              <label class="control-label modal-label">HP Codes: </label>
            </div>
            <div class="col-sm-8">
              <select class="form-control" name="hp_codes" id="hp_codes" multiple readonly>
              </select>
            </div>
          </div>

当我在浏览器中调试它时,它当前显示 $ 这一行 $('#hp_codes').each(function() { 未定义。我不确定如何解决这个问题,因为它之前工作正常。

编辑:如果没有 JQuery,它应该是这样工作的

window.addEventListener('DOMContentLoaded', () => {
  let hprops = document.querySelector('#hp_codes')
  document.querySelector('#hazards').addEventListener('change', e => {
    let options = e.target.options;
    let hazards = [];
    for (var i = 0, l = options.length; i < l; i++) {
      if (options[i].selected) {
        hazards.push(options[i].value);
      }
    }

    hprops.innerHTML = '';
    hprops.setAttribute('disabled', true); // disable until we get the data in there
    // ajax to get actual data ...
    let results = []
    if (hazards.includes("H200") || hazards.includes("H201")) results.push('HP1')
    if (hazards.includes('H300') || hazards.includes("H301")) results.push('HP6')
    if (hazards.includes('H400') || hazards.includes("H410")) results.push('HP14')

    results.forEach(r => hprops.innerHTML += `<option selected value='${r}'>${r}</option?`)
    hprops.removeAttribute('disabled');

  })
})

// array_unique compressed:
    function array_unique(d){var c="",b={},e="";var a=function(h,g){var f="";for(f in g){if(g.hasOwnProperty(f)){if((g[f]+"")===(h+"")){return f}}}return false};for(c in d){if(d.hasOwnProperty(c)){e=d[c];if(false===a(e,b)){b[c]=e}}}return b}


var optionValues = [];
$('#hp_codes').each(function() {
  optionValues.push($(this).val());
  $(this).remove(); // remove the option element
});

var cleanedArray = array_unique(optionValues); // clean the array

// let's go to paint the new options
for(var i in cleanedArray) {
  var opt = $('<option/>')
                .attr('value', cleanedArray[i]) // note that the value is equal than the text
                .text(cleanedArray[i]);
  $('#hp_codes').append(opt);
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>

          <div class="row form-group">
            <div class="col-sm-4">
              <label class="control-label modal-label">Hazard Statements: </label>
              <span class="text-danger">*</span> </div>
            <div class="mb-3 col-sm-8">
              <select class="form-control" id="hazards" name="hazards" multiple required>           
              <option value="H200">H200</option>
              <option value="H201">H201</option>              
              <option value="H300">H300</option>
              <option value="H301">H301</option>              
              <option value="H400">H400</option>
              <option value="H410">H410</option>              
              </select>             
            </div>
          </div>
          </br>
          <div class="row form-group">
            <div class="col-sm-4">
              <label class="control-label modal-label">HP Codes: </label>
            </div>
            <div class="col-sm-8">
              <select class="form-control" name="hp_codes" id="hp_codes" multiple readonly>
              </select>
            </div>
          </div>

简化了您的代码并放置了触发更改的核心逻辑。这将自动对危险选项中的任何选择或删除做出反应。

<html>
    <head>
        <title>Expense Tracker</title>

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
<script>
$(document).ready(function() {
    $('#hazards').select2();

$('#hazards').on('change', function(){

  console.log($(this).val());

  $('#hp_codes').html('');

     $($(this).val()).each(function(i, node){

         //node is the value selected from Hazards

         //do the db call here.. I have just used 1 value, but this can be array of values resulted from DB

          var opt = $('<option/>')
                .attr('value', node+' - DB options') // note that the value is equal than the text
                .text(node+' - DB options');
          $('#hp_codes').append(opt);

     });

   });
});


</script>
    </head>
    <body>
    

          <div class="row form-group">
            <div class="col-sm-4">
              <label class="control-label modal-label">Hazard Statements: </label>
              <span class="text-danger">*</span> </div>
            <div class="mb-3 col-sm-8">
              <select class="form-control select2" data-toggle="select2" id="hazards" name="hazards" multiple required>           
              <option value="H200">H200</option>
              <option value="H201">H201</option>              
              <option value="H300">H300</option>
              <option value="H301">H301</option>              
              <option value="H400">H400</option>
              <option value="H410">H410</option>              
              </select>             
            </div>
          </div>
          </br>
          <div class="row form-group">
            <div class="col-sm-4">
              <label class="control-label modal-label">HP Codes: </label>
            </div>
            <div class="col-sm-8">
              <select class="form-control" name="hp_codes" id="hp_codes" multiple readonly>
              </select>
            </div>
          </div>
</body>

</html>

更接近您的原始代码,我相信这是需要的? 由于某些原因 #hazardsaddEventListener 没有触发,所以我改用 $('#hazards').on('change', ...

另外,似乎DOMContentLoaded处理程序之后的所有代码都没有使用?
不管怎样,我添加了一个替代的唯一函数来过滤数组,commented-out,如果你觉得它有用的话。

//    $(document).ready(function() {
//        $('#hazards').select2();
//    });

window.addEventListener('DOMContentLoaded', () => {
    $('#hazards').select2();
  let hprops = document.getElementById('hp_codes')
//      document.querySelector('#hazards').addEventListener('change', e => {
// The hazards addEventListener was not firing?
  $('#hazards').on('change', e => {
    let options = e.target.options;
    let hazards = [];
    for (var i = 0, l = options.length; i < l; i++) {
      if (options[i].selected) {
        hazards.push(options[i].value);
      }
    }

    hprops.innerHTML = '';
    hprops.setAttribute('disabled', true); // disable until we get the data in there
    // ajax to get actual data ...
    let results = []
    if (hazards.includes("H200") || hazards.includes("H201")) results.push('HP1')
    if (hazards.includes('H300') || hazards.includes("H301")) results.push('HP6')
    if (hazards.includes('H400') || hazards.includes("H410")) results.push('HP14')

    results.forEach(r => hprops.innerHTML += `<option selected value="${r}">${r}</option>`)
    hprops.removeAttribute('disabled');
  })
})

// array_unique compressed:
function array_unique(d){var c="",b={},e="";var a=function(h,g){var f="";for(f in g){if(g.hasOwnProperty(f)){if((g[f]+"")===(h+"")){return f}}}return false};for(c in d){if(d.hasOwnProperty(c)){e=d[c];if(false===a(e,b)){b[c]=e}}}return b}
/* // an alternative unique
function onlyUnique(value, index, self) {
    return self.indexOf(value) === index;
}
*/
var optionValues = [];
//    $('#hp_codes').each(function() { // this removed the select!
$('#hp_codes').children().each(function() {
  optionValues.push($(this).val());
  $(this).remove(); // remove the option element
});

var cleanedArray = array_unique(optionValues); // clean the array
//    var cleanedArray = optionValues.filter(onlyUnique); // clean the array

// let's go to paint the new options
for(var i in cleanedArray) {
  var opt = $('<option/>')
                .prop('value', cleanedArray[i]) // note that the value is equal than the text
                .text(cleanedArray[i]);
  $('#hp_codes').append(opt);
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>

          <div class="row form-group">
            <div class="col-sm-4">
              <label class="control-label modal-label">Hazard Statements: </label>
              <span class="text-danger">*</span> </div>
            <div class="mb-3 col-sm-8">
              <select class="form-control select2" data-toggle="select2" id="hazards" name="hazards" multiple required>           
              <option value="H200">H200</option>
              <option value="H201">H201</option>              
              <option value="H300">H300</option>
              <option value="H301">H301</option>              
              <option value="H400">H400</option>
              <option value="H410">H410</option>              
              </select>             
            </div>
          </div>
          </br>
          <div class="row form-group">
            <div class="col-sm-4">
              <label class="control-label modal-label">HP Codes: </label>
            </div>
            <div class="col-sm-8">
              <select class="form-control" name="hp_codes" id="hp_codes" multiple readonly>
              </select>
            </div>
          </div>