根据第一个选择动态填充第二个下拉菜单

Posted

技术标签:

【中文标题】根据第一个选择动态填充第二个下拉菜单【英文标题】:Dynamically populate second drop down menu based on first selection 【发布时间】:2021-09-30 21:28:37 【问题描述】:

我正在使用以下代码动态填充两个下拉菜单“searchProject”和“searchHR”。用户可以从“searchProject”中选择一个值,从“searchHR”中选择多个值来过滤数据表。

我正在尝试让第二个下拉菜单“searchHR”填充基于在第一个下拉菜单“searchProject”中选择的单个值的值。

这是我当前的代码:

  var sortFunction = function (a, b) 
        if (a < b) return -1;
        if (a > b) return 1;
        return 0;
    ;
       

 $(document).ready(function () 
        var ex_table = $('#data_table').DataTable(
            "order": [],
            pageLength: 50,
            ajax: 
                url: '/db',
                dataSrc: "",
                type: "POST",
                'data': function (d) 
                    return $.extend(, d, 
                        "project_name": $('#searchProject').val(),
                        "hour": $('#searchHR').val(),
                    );
                ,
                "serverSide": true,
            ,
    
            columns: [
                data: 'project_name',
                data: 'id',
                data: 'hour',  
            ],
            "initComplete": function () 
                ex_table.columns([0]).every(function () 
                    const column = this;
                    const select = $('#searchProject')
                        .on('change', function () 
                            const Project_val = $(this).val();
                            column.search(Project_val).draw();
                        );
                    column.data().unique().sort().each(function (d) 
                        select.append('<option value="' + d + '">' + d + '</option>')
                    );
                );
    
    
                ex_table.columns([2]).every(function () 
                    const column = this;
                    const select = $('#searchHR')
                        .on('change', function () 
                            var vals = $('option:selected', this).map(function (index, element) 
                                return $.fn.dataTable.util.escapeRegex($(element).val());
                            ).toArray().join('|');
    
                            column.search(vals.length > 0 ? '^(' + vals + ')$' : '', true, false).draw();
                        );
    
                    column.data().unique().sort(sortFunction).each(function (d) 
                        select.append('<option value="' + d + '">' + d + '</option>')
                    );
                );
            
        );
)

HTML:

    <label for="searchProject"></label><select id="searchProject" class="js-example-basic-single" style="width: 10%">
    <option></option>
</select>
    <label for="searchHR"></label><select id="searchHR" class="js-example-basic-multiple" multiple="multiple" style="width:15%">
    <option></option>
</select>

任何帮助将不胜感激。谢谢。

【问题讨论】:

【参考方案1】:

这是一种方法 - 我对代码进行了注释以提供对主要步骤的解释。大部分复杂性来自 (a) 管理两个选择小部件之间的关系,以及 (b) 处理来自多选的值数组。

// inline test data:
var dataSet = [
    
      "id": "123",
      "name": "Tiger Nixon",
      "position": "System Architect",
      "salary": "$320,800",
      "start_date": "2011/04/25",
      "office": "Edinburgh",
      "extn": "5421"
    ,
    
      "id": "456",
      "name": "Donna Snider",
      "position": "Customer Support",
      "salary": "$112,000",
      "start_date": "2011/01/25",
      "office": "New York",
      "extn": "4226"
    ,
    
      "id": "567",
      "name": "Cedric Kelly",
      "position": "Senior javascript Developer",
      "salary": "$433,060",
      "start_date": "2012/03/29",
      "office": "Edinburgh",
      "extn": "6224"
    ,
    
      "id": "432",
      "name": "Airi Satou",
      "position": "Accountant",
      "salary": "$162,700",
      "start_date": "2008/11/28",
      "office": "Tokyo",
      "extn": "5407"
    ,
    
      "id": "987",
      "name": "Brielle Williamson",
      "position": "Integration Specialist",
      "salary": "$372,000",
      "start_date": "2012/12/02",
      "office": "New York",
      "extn": "4804"
    
  ];

$(document).ready(function() 

var table = $('#example').DataTable( 
  data: dataSet,
  orderCellsTop: true,
  columns: [
     data: "name" ,
     data: "office" ,
     data: "position" ,
     data: "extn" 
  ],
  initComplete: function () 
    this.api().columns( [1, 2] ).every( function () 
      var column = this;
      var colIdx = column.index();
      var node;
      var select;
      if (colIdx === 1) 
        node = $('#office_select');
        select = $('<select><option value=""></option></select>');
       else 
        node = $('#position_select');
        select = $('<select multiple><option value=""></option></select>');
      

      select.appendTo( $(node).empty() )
        .on( 'change', function () 
          // the contents of the multi-select, as an array of values:
          var val = $(this).val();
          if (colIdx === 1)  // this is the standard select column (for "office")
            val = $.fn.dataTable.util.escapeRegex(val);
            column.search( val ? '^' + val + '$' : '', true, false ).draw();
            rebuildPositionSelect();
           else  // this is the multi-select column (for "position"):
            // build a string containing the pipe-separated multiselect values, but
            // with each value escaped for any regex characters it may contain:
            var vals = val.map(x => $.fn.dataTable.util.escapeRegex(x)).join('|');           
            column.search( vals ? '^' + vals + '$' : '', true, false ).draw();
          
         );

      column.data().unique().sort().each( function ( val ) 
        select.append( '<option value="' + val +'">' + val + '</option>' )
       );

     );
  
 ); 

function rebuildPositionSelect() 
  var select = $('#position_select select').empty().append('<option value=""></option>');
  // note the use of search:'applied' here, to only capture visible "position" values:
  var column = table.column(2, search:'applied');
  // we need to reset the "position" search back to "none", to unfilter that column,
  // otherwise our new filter may not find the already filtered data:
  column.search('').draw();
  column.data().unique().sort().each( function ( val ) 
    select.append( '<option value="' + val +'">' + val + '</option>' );
   );


 );
<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Demo</title>
  <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
  <script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.js"></script>
  <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.css">
  <link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">

</head>

<body>

<div style="margin: 20px;">

    <div>
        <span>Office: </span>
        <span id="office_select"></span>
        <span> Position: </span>
        <span id="position_select"></span>
    </div>

    <br><br>

    <table id="example" class="display dataTable cell-border" style="width:100%">
        <thead>
            <tr>
                <th>Name</th>
                <th>Office</th>
                <th>Position</th>
                <th>Extn.</th>
            </tr>
        </thead>
    </table>

</div>

</body>
</html>

一些注意事项:

    用户界面可以改进!选择下拉菜单和多选没有任何样式/定位 CSS。

    因为从第一个(“办公室”)下拉列表到第二个(“职位”)多选存在依赖关系,所以每当我们对第一个下拉菜单进行更改时,我们都必须清除所有多选选择-下。如果没有这个,您最终可能会得到与所选下拉列表无关的多选值。

    代码可以(并且可能应该)重新排列成组织更好的结构。目前,我的大部分代码都只是转储到initComplete 函数中。

(我纯粹的个人偏好是通常避免这种类型的选择依赖,因为它可能会让用户感到惊讶。)

【讨论】:

以上是关于根据第一个选择动态填充第二个下拉菜单的主要内容,如果未能解决你的问题,请参考以下文章

Wordpress 选项页面中动态生成的下拉菜单

根据另一个下拉列表中的选择填充一个下拉列表,然后重定向

使用与第一个下拉列表相同的值填充第二个下拉列表

使用 thymeleaf、spring boot 的动态下拉菜单

根据下拉列表的值创建 2 个下拉列表和一个表

使用Angular 4根据第一个下拉列表选择第二个下拉列表