jQuery Datatables自定义列搜索

3
我已经研究了一段时间,但有用的信息正在枯竭,没有解决方案。
我正在使用Datatables,在某些列中,我正在显示一个Chosen多选框,以允许用户在添加数据后通过继续进行选择来编辑其数据。

enter image description here

我已经使用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中删除了Chosen元素,而没有通过使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。如果用户在将选项添加到表格后更改选择框选项,可能仍会出现问题,但我会等到那时再看。

1个回答

2
我认为你使用$.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选择器将所选多选项值收集到一个字符串中。
最后,我们查看搜索词是否包含在我们构建的字符串中。我们分别对两列进行此操作,以便整个表格过滤一致。
此实现假定只有两列包含这些Chosen多选项 - 并且它们是前两列。
我还使用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>

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