Jquery Datatables 自定义列搜索

马修·莱西

我已经研究了一段时间,有用的信息在没有解决方案的情况下枯竭。

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

在此处输入图片说明

我有使用 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 文档提到您可以为正交数据定义一个列过滤器函数,但没有给出这样的例子,我也在努力在网上找到任何东西。我对此的尝试是将以下内容添加到 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。如果用户在将选择框选项添加到表格后对其进行更改,这可能仍然会出现问题,但我会在到达时查看。

安德鲁詹姆斯

我认为您的使用方法$.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;
      }
    }
  );

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

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

然后我们使用 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>

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章