如何在JavaScript / jQuery中基于另一个select禁用select的多个选项

3

我正在使用 Select2 JQuery 插件。我有两个选择框tableHeadertableBody,可以在每个选择框中选择多个标签。

我想做的是:

  • 如果我在第一个选择框中选择了一个或多个选项,它们将被禁用在第二个选择框中,反之亦然;如果我从一个选择框中取消选择一个选项,则在另一个选择框中会启用该选项。

我的做法是:

我创建了一个数组selections,用于存储从第一个选择框中选择的选项,然后我循环遍历第二个选择框的选项,并检查该值是否存在于数组中,然后将其禁用。

我想这个逻辑应该是正确的。只是不知道为什么我的选项没有被禁用。请问有什么建议吗?

这是我的代码及解释:

$(document).ready(function() { 
    
    // this function to search and show matched input
    function matchCustom(params, data) {

    if ($.trim(params.term) === '') { return data; }

    if (typeof data.text === 'undefined') { return null; }

    if (data.text.toUpperCase().indexOf(params.term.toUpperCase()) > -1) {
      var modifiedData = $.extend({}, data, true);
      modifiedData.text += '';
     return modifiedData; }

    return null; }

  $(".select2").select2({
  matcher: matchCustom
  });

//if you select or unselect option trigger this
$('#tableHeader').change(function() {

    var selections = [];
    // if you select an option then add the value in array
   $('#tableHeader').on('select2:select', function (e) { 
    
      $('#tableHeader option:selected').each(function(){
        if($(this).val())
            selections.push($(this).val());  });
     
     });
     // if you unselect an option then remove from array
   $('#tableHeader').on('select2:unselect', function (e) {
      var unselected = e.params.data.id;
      selections.splice( $.inArray(unselected, selections), 1 );

    }); 
     
      console.log(selections);

     // loop through other select option and check if value exists in array then disable it
     $('#tableBody option').each(function() {
       if(jQuery.inArray($(this).val(), selections) !== -1) {  
       console.log($(this).val());
      $('#tableBody option[value="'+ $(this).val() + '"]').prop('disabled',true); }

      });
      
     

    });
    
    // do the same if you start with second select 
    $('#tableBody').change(function() {

    var selections = [];
    
   $('#tableBody').on('select2:select', function (e) { 
    
      $('#tableBody option:selected').each(function(){
        if($(this).val())
            selections.push($(this).val());  });
     
     });
     
   $('#tableBody').on('select2:unselect', function (e) {
      var unselected = e.params.data.id;
      selections.splice( $.inArray(unselected, selections), 1 );

    }); 
     
      console.log(selections);

     $('#tableHeader option').each(function() {
       if(jQuery.inArray($(this).val(), selections) !== -1) {  
       console.log($(this).val());
      $('#tableHeader option[value="'+ $(this).val() + '"]').prop('disabled',true); }

      });
      
     

    });

});
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/css/select2.min.css" rel="stylesheet"/>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/js/select2.min.js"></script>

<span>Table Header</span>
<select id="tableHeader" class="select2 select2-multiple" style="width: 100%" multiple="multiple" data-placeholder="Choose">      
<option value="Geo">Geo</option>
<option value="Region">Region</option>
<option value="Country">Country</option>
<option value="Order Numer">Order Numer</option>
<option value="Order Value">Order Value</option>
<option value="Brand">Brand</option>
<option value="Quantity">Quantity</option>
<option value="Price">Price</option>
<option value="Revenue">Revenue</option>
<option value="Currency">Currency</option>
<option value="Created Date">Created Date</option>
<option value="Created By">Created By</option>              
</select>
<br>
<span>Table Body</span>
<select id="tableBody" class="select2 select2-multiple" style="width: 100%" multiple="multiple" data-placeholder="Choose">      
<option value="Geo">Geo</option>
<option value="Region">Region</option>
<option value="Country">Country</option>
<option value="Order Numer">Order Numer</option>
<option value="Order Value">Order Value</option>
<option value="Brand">Brand</option>
<option value="Quantity">Quantity</option>
<option value="Price">Price</option>
<option value="Revenue">Revenue</option>
<option value="Currency">Currency</option>
<option value="Created Date">Created Date</option>
<option value="Created By">Created By</option>              
</select>


我能看到的第一件事是,你可以像这样优化你的代码:var $tableHeader = $('#tableHeader'),然后利用这个变量。我猜第一个change事件也会包含有关所选项目的信息,不需要嵌套on子句...这不是你问题的答案,但可以帮助使代码更易读。 - MattOpen
2个回答

2

我认为您的想法本身没问题,但是您可能会让自己的工作变得更加复杂。只需在每次更改每个选择器的值时,循环遍历其他选择器,并逐一禁用具有相同值的选择器即可。

$(document).ready(function() {

  // this function to search and show matched input
  function matchCustom(params, data) {

    if ($.trim(params.term) === '') {
      return data;
    }

    if (typeof data.text === 'undefined') {
      return null;
    }

    if (data.text.toUpperCase().indexOf(params.term.toUpperCase()) > -1) {
      var modifiedData = $.extend({}, data, true);
      modifiedData.text += '';
      return modifiedData;
    }

    return null;
  }

  $(".select2").select2({
    matcher: matchCustom
  });

  $('#tableHeader').change(function() {

    var tableHeader = $(this).val();
    var tableBody = $("#tableBody")[0];

    $.each(tableBody.options, function(i, item) {
      if (tableHeader.includes(item.value)) {
        $(item).prop("disabled", true);
      } else {
        $(item).prop("disabled", false);
      }
    });

  });

  $('#tableBody').change(function() {

    var tableBody = $(this).val();
    var tableHeader = $("#tableHeader")[0];

    $.each(tableHeader.options, function(i, item) {
      if (tableBody.includes(item.value)) {
        $(item).prop("disabled", true);
      } else {
        $(item).prop("disabled", false);
      }
    });

  });

});
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/css/select2.min.css" rel="stylesheet" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/js/select2.min.js"></script>

<span>Table Header</span>
<select id="tableHeader" class="select2 select2-multiple" style="width: 100%" multiple="multiple" data-placeholder="Choose">
  <option value="Geo">Geo</option>
  <option value="Region">Region</option>
  <option value="Country">Country</option>
  <option value="Order Numer">Order Numer</option>
  <option value="Order Value">Order Value</option>
  <option value="Brand">Brand</option>
  <option value="Quantity">Quantity</option>
  <option value="Price">Price</option>
  <option value="Revenue">Revenue</option>
  <option value="Currency">Currency</option>
  <option value="Created Date">Created Date</option>
  <option value="Created By">Created By</option>
</select>
<br>
<span>Table Body</span>
<select id="tableBody" class="select2 select2-multiple" style="width: 100%" multiple="multiple" data-placeholder="Choose">
  <option value="Geo">Geo</option>
  <option value="Region">Region</option>
  <option value="Country">Country</option>
  <option value="Order Numer">Order Numer</option>
  <option value="Order Value">Order Value</option>
  <option value="Brand">Brand</option>
  <option value="Quantity">Quantity</option>
  <option value="Price">Price</option>
  <option value="Revenue">Revenue</option>
  <option value="Currency">Currency</option>
  <option value="Created Date">Created Date</option>
  <option value="Created By">Created By</option>
</select>


1
非常感谢,这正是我需要的 :) - DevTN

0

只需启用和禁用彼此的更改事件,如下所示

$(document).ready(function() { 
    
        // this function to search and show matched input
    function matchCustom(params, data) {

    if ($.trim(params.term) === '') { return data; }

    if (typeof data.text === 'undefined') { return null; }

    if (data.text.toUpperCase().indexOf(params.term.toUpperCase()) > -1) {
      var modifiedData = $.extend({}, data, true);
      modifiedData.text += '';
     return modifiedData; }

    return null; }

  $(".select2").select2({
  matcher: matchCustom
  });
    
    var disableTableBody = function(value){
           $('#tableBody option[value="'+ value +'"]').prop('disabled',true);
    };
    
    var enableTableBody = function(value){
       $('#tableBody option[value="'+ value +'"]').prop('disabled',false);
    };
    
       var disableTableHeader = function(value){
           $('#tableHeader option[value="'+ value +'"]').prop('disabled',true);
    };
    
    var enableTableHeader = function(value){
       $('#tableHeader option[value="'+ value +'"]').prop('disabled',false);
    };
    
    
   $("#tableHeader").change(function(){
        disableTableBody($(this).val());  
   });
   
   $('#tableHeader').on("select2:unselecting", function(e){
      enableTableBody($(this).val());
   });

   $("#tableBody").change(function(){
        disableTableHeader($(this).val());  
   });
   
   $('#tableBody').on("select2:unselecting", function(e){
      enableTableHeader($(this).val());
   });

});
   
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/css/select2.min.css" rel="stylesheet"/>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/js/select2.min.js"></script>

<span>Table Header</span>
<select id="tableHeader" class="select2 select2-multiple" style="width: 100%" multiple="multiple" data-placeholder="Choose">      
<option value="Geo">Geo</option>
<option value="Region">Region</option>
<option value="Country">Country</option>
<option value="Order Numer">Order Numer</option>
<option value="Order Value">Order Value</option>
<option value="Brand">Brand</option>
<option value="Quantity">Quantity</option>
<option value="Price">Price</option>
<option value="Revenue">Revenue</option>
<option value="Currency">Currency</option>
<option value="Created Date">Created Date</option>
<option value="Created By">Created By</option>              
</select>
<br>
<span>Table Body</span>
<select id="tableBody" class="select2 select2-multiple" style="width: 100%" multiple="multiple" data-placeholder="Choose">      
<option value="Geo">Geo</option>
<option value="Region">Region</option>
<option value="Country">Country</option>
<option value="Order Numer">Order Numer</option>
<option value="Order Value">Order Value</option>
<option value="Brand">Brand</option>
<option value="Quantity">Quantity</option>
<option value="Price">Price</option>
<option value="Revenue">Revenue</option>
<option value="Currency">Currency</option>
<option value="Created Date">Created Date</option>
<option value="Created By">Created By</option>              
</select>


谢谢你的尝试,但它没有起作用。我采取了类似的方法,它只禁用您选择的第一个标签,其他标签没有被禁用。您可以通过运行您的代码并选择多个选项来验证这一点。您将只有第一个选择被禁用,其他不会。 - DevTN

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