html表格的多个过滤器

时间:2018-08-09 17:13:08

标签: javascript jquery css html-table

我的视图中有html表,我想使用多个过滤器进行过滤。在这种情况下,我有3个过滤器,但我可以有更多过滤器。

这里很少有代码来显示问题

$(document).ready(function () {
   
   

    $('#datefilterfrom').on("change", filterRows);
    $('#datefilterto').on("change", filterRows);
    $('#projectfilter').on("change", filterProject);
    $('#servicefilter').on("change", filterService);
});

function filterRows() {
    var from = $('#datefilterfrom').val();
    var to = $('#datefilterto').val();

    if (!from && !to) { // no value for from and to
        return;
    }

    from = from || '1970-01-01'; // default from to a old date if it is not set
    to = to || '2999-12-31';

    var dateFrom = moment(from);
    var dateTo = moment(to);

    $('#testTable tr').each(function (i, tr) {
        var val = $(tr).find("td:nth-child(2)").text();
        var dateVal = moment(val, "DD/MM/YYYY");
        var visible = (dateVal.isBetween(dateFrom, dateTo, null, [])) ? "" : "none"; // [] for inclusive
        $(tr).css('display', visible);
    });
}
function filterProject() {
    let dumb = this.options.selectedIndex;
    dumb = this.options[dumb].innerHTML;
    var filter, table, tr, td, i;
    filter = dumb.toUpperCase();
    table = document.getElementById("testTable");
    tr = table.getElementsByTagName("tr");
    for (i = 0; i < tr.length; i++) {
        td = tr[i].getElementsByTagName("td")[2];
        if (td) {
            if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
                tr[i].style.display = "table-row";
            } else {
                tr[i].style.display = "none";
            }
        }

    }
}

function filterService() {
    let dumb = this.options.selectedIndex;
    dumb = this.options[dumb].innerHTML;
    var filter, table, tr, td, i;
    filter = dumb.toUpperCase();
    table = document.getElementById("testTable");
    tr = table.getElementsByTagName("tr");
    for (i = 0; i < tr.length; i++) {
        td = tr[i].getElementsByTagName("td")[3];
        if (td) {
            if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
                tr[i].style.display = "table-row";
            } else {
                tr[i].style.display = "none";
            }
        }

    }
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/moment/moment/2.2.1/min/moment.min.js"></script>
   <div class="row">
        <div class="col-md-3">
            <h4>Date from</h4>
            <input type="date" class="form-control" id="datefilterfrom" data-date-split-input="true">
        </div>
        <div class="col-md-3">
            <h4>Date to</h4>
            <input type="date"  class="form-control" id="datefilterto" data-date-split-input="true">
        </div>
        <div class="col-md-2">
            <h4>Project</h4>
           <select id="projectfilter" name="projectfilter" class="form-control"><option value="1">Test project</option><option value="2">Test2</option></select>
        </div>
     <div class="col-md-2">
            <h4>Service</h4>
           <select id="servicefilter" name="servicefilter" class="form-control"><option value="1">Test service</option><option value="2">Test2 service</option></select>
        </div>
    </div>
<table id="testTable" class="table">
            <thead>
                <tr>
                    <th scope="col">#</th>
                    <th scope="col">Date</th>
                    <th scope="col">Project</th>
                   <th scope="col">Service</th>
               
                </tr>
            </thead>
            <tbody id="report">
              <tr>
                <td class="proposalId">9</td><td> 17/07/2018</td> <td> Test project</td><td> Test service</td>
              </tr>
              <tr><td class="proposalId">8</td><td> 18/07/2018</td><td> Test project</td><td> Test2  service</td></tr>
              <tr><td class="proposalId">7</td><td> 17/07/2018</td><td> Test2</td><td> Test2 service</td></tr>
              <tr style=""><td class="proposalId">3</td><td> 19/07/2018</td><td> Test2</td><td> Test service</td></tr>
              
    </tbody>
        </table>

如果您这样设置过滤器 enter image description here

您将拥有这个

enter image description here

这是不对的。因为我只需要测试2个项目,所以一行。

我的问题在哪里以及如何解决?

这里是代码的密码笔

  

https://codepen.io/suhomlineugene/pen/pZqyEN

2 个答案:

答案 0 :(得分:0)

现在,每个过滤器都有一个单独的功能,每个功能都会忽略其他过滤器的设置并覆盖其结果。

相反,您需要将它们组合成一个函数,该函数将 all 个过滤器考虑在内。

与其将所有代码从字面上组合成一个复杂的函数(这很难维护),一种方法是让单个主函数使所有行可见,然后依次调用其他每个过滤器函数;这些功能只会隐藏正在过滤的行。最后剩下的就是与所有过滤器选择匹配的行。

$(document).ready(function () {
    $('#datefilterfrom, #datefilterto, #projectfilter, #servicefilter').on("change", filterAll);
});

function filterAll() {
    $('#testTable tr').show();
    filterRows();
    filterProject();
    filterService();
    // ...etc
}

function filterRows() {  // repeat for filterProject(), filterService(), etc
    // same as your original code, except only hide non-matching rows, do not
    // show matching rows (because filterAll() already took care of that, and
    // you don't want to undo what other filters may have hidden.)
}

(或者,不显示所有内容,而是让每个单独的过滤器逐渐隐藏行,您可以让filterAll()构建一个包含所有行的数组,将其传递给单独的过滤器函数,该函数将从中删除项目,然后使用最终显示/隐藏相应行的最终结果。)

答案 1 :(得分:0)

不会为您全部重写,但会为您提供纯文本搜索的基本概述:

从顶部输入创建过滤器数据数组。通过向每个过滤器控件添加data-col,您可以轻松确定表中要匹配的列

所以filter数组看起来像这样:

[
  {col:3, value:'test project'}
]

然后在行上使用jQuery filter(),在filterValues数组上使用Array#every(),并使用每个过滤器对象的列索引查找匹配的单元格文本

var $rows = $('tbody#report tr')
// add a class `table-filter` to all the top filtering elements
var $filters = $('.table-filter').change(function() {

  // create array of filter objects
  var filterArr = $filters.filter(function() {
    return this.value
  }).map(function() {
    var $el = $(this);
    var value = $el.is('select') ? $el.find(':selected').text() : $el.val()
    return {
      col: $el.data('col'),
      value: value.toLowerCase()
    }
  }).get();

  if (!filterArr.length) {
    // no filters show all rows
    $rows.show()
  } else {
    // hide all then filter out the  matching rows
    $rows.hide().filter(function() {
      var $row = $(this);
      // match every filter to whole row
      return filterArr.every(function(filterObj, i) {
        var cellText = $row.find('td').eq(filterObj.col).text().trim().toLowerCase();
        return cellText.includes(filterObj.value);
      })
    })
    // show the matches
    .show()
  }
});

Working demo for the two text search fields