【问题标题】:Jquery Datatables custom column searchingJquery Datatables 自定义列搜索
【发布时间】:2021-04-14 10:07:48
【问题描述】:

我已经对此进行了一段时间的研究,但有用的信息正在枯竭而没有解决方案。

我正在使用数据表,并且在某些列中,我显示了一个选择的多选框,以允许用户在添加数据后通过继续进行选择来编辑他们的数据。

我有使用 initComplete 的每列搜索框,它们会过滤列中的数据,但不是以可接受的方式;它们在选项的文本上匹配,也在选择元素的类上匹配,甚至在所有未选择的选项上匹配,因此它是无用的。

...,
initComplete: function () {
            // Apply the search
            this.api().columns().every(function () {
                var that = this;

                $('input', this.footer()).on('keyup change clear', function () {
                    if (that.search() !== this.value) {
                        that
                            .search(this.value)
                            .draw();
                    }
                });
            });
        }

我希望这仅匹配选择框的选定选项的文本。 编写函数以获取给定行中选择框的文本字符串数组很容易由我完成,但我正在努力找出在哪里可以将这样的自定义函数挂钩到 Datatables 流。

Datatables 文档提到您可以为正交数据定义列过滤器函数,但没有给出这方面的示例,我也很难在网上找到任何示例。 我的尝试是将以下内容添加到 DataTable 初始化中,但没有被调用:

...,
"columns": [          
            {
                filter: function (a,b,c) {
                    console.log('called from column filter');
                    console.log(arguments)
                    return false;
                }
            },
            {
                filter: function (a,b,c) {
                    console.log('called to column filter');
                    console.log(arguments)                 
                    return false;
                }
            },
            null  
        ]

感谢您的宝贵时间。

更新

所以我发现我可以将一个函数推送到 $.fn.dataTable.ext.search.push(...) 上,这似乎可以满足我的需求。 沿着这条路走下去,我发现在参数中传递的 html 列不包括我需要的 Chosen 生成的元素,只是预先选择的.... 我试过使用 table.rows.invalidate.draw 但这只是从 DOM 中删除选择的元素,而不是通过让 Datatables 传入预期的 html 数据来解决这个问题。

我希望传入的实际行 html 示例:

<td>
<select class="myclasses form-control" multiple="" style="display: none;">                    
    <option value="...">Bahamas</option>
    ...
</select>
<div class="chosen-container chosen-container-multi" title="" style="width: 437px;">
    <ul class="chosen-choices">
        <li class="search-choice">
            <span>Greece</span>
            <a class="search-choice-close" data-option-array-index="4"></a>
        </li>
        <li class="search-choice">
            <span>Belgium</span>
            <a class="search-choice-close" data-option-array-index="6"></a>
        </li>
        <li class="search-choice">
            <span>France</span>
            <a class="search-choice-close" data-option-array-index="7"></a></li><li class="search-field">
            <input class="chosen-search-input" type="text" autocomplete="off" value="Select some options" style="width: 25px;">
        </li>
    </ul>
    <div class="chosen-drop">
      <ul class="chosen-results"></ul>
    </div>
</div>
</td>

搜索调用中的实际参数数据,似乎处于预选状态。这就是为什么我希望 .invalidate() 解决这个问题...

<select class="myclasses form-control" multiple>                    
    <option value="...">Bahamas</option>
</select>

我现在正在研究在将选择的 html 添加到表之前生成选择的 html。如果用户在将选择框选项添加到表格后对其进行更改,这可能仍然存在问题,但我会在到达那里时看到。

【问题讨论】:

    标签: jquery datatables


    【解决方案1】:

    我认为您使用$.fn.dataTable.ext.search 的方法是正确的方法,因为与search() API 函数不同,这使您能够访问可以找到用户选择的DOM(即在DataTables 对象)。

    但是,由于$.fn.dataTable.ext.search 不仅限于一列,因此需要做一些额外的工作来确保跨不同列的组合搜索仍然正常工作。

    这是一个基本的例子,但它展示了一种方法。

    每个input 事件所做的唯一事情就是触发重新绘制表格。这种重新绘制又会触发全局搜索功能:

        initComplete: function () {
          var api = this.api();
          api.columns().each(function () {
            $('input', this.footer()).on('keyup change clear', function () {
              api.draw();
            });
          });
        }
    

    搜索功能如下。代码可以简化 - 但它显示了基本方法:

      $.fn.dataTable.ext.search.push(
        function( settings, searchData, index, rowData, counter ) { 
    
          var fromFilter = $( '#in_0' ).val();
          var toFilter = $( '#in_1' ).val();
    
          var trNode = table.row( [index] ).node();
    
          var fromTdNode = $( "td:nth-child(1)", trNode );
          var fromSelectedValNodes = $( "select option:selected", fromTdNode );   
          var fromSelections = '';
          fromSelectedValNodes.each(function() {
            fromSelections += ( $( this ).val() + ', ' ); 
          });
    
          var toTdNode = $( "td:nth-child(2)", trNode );
          var toSelectedValNodes = $( "select option:selected", toTdNode );   
          var toSelections = '';
          toSelectedValNodes.each(function() {
            toSelections += ( $( this ).val() + ', ' ); 
          });
          
          if ( fromSelections.trim().toLowerCase().includes( fromFilter.trim().toLowerCase() ) &&
                  toSelections.trim().toLowerCase().includes( toFilter.trim().toLowerCase() ) ) {
            return true;
          } else {
              return false;
          }
        }
      );
    

    我们检索用户提供的两个搜索值,并将它们保存在fromFiltertoFilter

    然后,对于包含多选的两列中的每一列,我们检索选定值的文本。我们使用 DataTables API 从每个 DataTables 行中获取相关的 node() 对象。

    然后我们使用 jQuery 选择器将选中的多选值收集到一个字符串中。

    最后我们看看搜索词是否包含在我们构建的字符串中。我们分别对两列中的每一列执行此操作,以便一致地过滤整个表。

    此实现假设只有 2 列包含这些选择的多选 - 而且它们是前 2 列。

    我还使用dom 选项从DataTable 中删除了默认的全局搜索输入框,因为这也会导致$.fn.dataTable.ext.search 被调用。

    最后说明:我为小型演示加载数据的方式似乎与您的数据加载不同 - 因此,如果可能需要更改,这里是我完整的独立演示:

    <!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">
    
      <!-- chosen select library -->
      <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.min.css">
      <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.jquery.min.js"></script>
    
    
    </head>
    
    <body>
    
    <div style="margin: 20px;">
    
        <table id="example" class="display dataTable cell-border" style="width:100%">
            <thead>
                <tr>
                    <th>From Country</th><th>To Country</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td></td><td></td>
                </tr>
                <tr>
                    <td></td><td></td>
                </tr>
                <tr>
                    <td></td><td></td>
                </tr>
                <tr>
                    <td></td><td></td>
                </tr>
                <tr>
                    <td></td><td></td>
                </tr>
            </tbody>
            <tfoot>
                <tr>
                    <th></th><th></th>
                </tr>
            </tfoot>
        </table>
    
    </div>
    
    <script>
    
    $(document).ready(function() {
    
      $('#example tfoot th').each( function ( idx ) {
        var title = $(this).text();
        $(this).html( '<input id="in_' + idx + '" type="text" placeholder="Search ' + title + '"/>' );
      } );
    
      var table = $('#example').DataTable( {
    
        dom: 'lrtip', // removed "f" for "filter".
    
        columnDefs: [
          {
            targets: [ 0, 1 ],
            render: function ( data, type, row ) {
              var select = $('<select multiple class="chosen-select"><option value=""></option></select>');
              select.append( '<option value="Argentina">Argentina</option>' );
              select.append( '<option value="Brazil">Brazil</option>' );
              select.append( '<option value="Cuba">Cuba</option>' );
              select.append( '<option value="Denmark">Denmark</option>' );
              select.append( '<option value="Egypt">Egypt</option>' );
              return select[0].outerHTML;
            }        
          }
        ],
    
        initComplete: function () {
          var api = this.api();
          api.columns().each(function () {
            $('input', this.footer()).on('keyup change clear', function () {
              api.draw();
            });
          });
        }
      } );
    
      $.fn.dataTable.ext.search.push(
        function( settings, searchData, index, rowData, counter ) { 
    
          var fromFilter = $( '#in_0' ).val();
          var toFilter = $( '#in_1' ).val();
    
          var trNode = table.row( [index] ).node();
    
          var fromTdNode = $( "td:nth-child(1)", trNode );
          var fromSelectedValNodes = $( "select option:selected", fromTdNode );   
          var fromSelections = '';
          fromSelectedValNodes.each(function() {
            fromSelections += ( $( this ).val() + ', ' ); 
          });
    
          var toTdNode = $( "td:nth-child(2)", trNode );
          var toSelectedValNodes = $( "select option:selected", toTdNode );   
          var toSelections = '';
          toSelectedValNodes.each(function() {
            toSelections += ( $( this ).val() + ', ' ); 
          });
          
          if ( fromSelections.trim().toLowerCase().includes( fromFilter.trim().toLowerCase() ) &&
                  toSelections.trim().toLowerCase().includes( toFilter.trim().toLowerCase() ) ) {
            return true;
          } else {
              return false;
          }
        }
      );
    
      $(".chosen-select").chosen({
        width: "75%"
      });
    
    
    } );
    
    </script>
    
    </body>
    </html>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-26
      • 2021-07-22
      • 1970-01-01
      • 2015-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多