使用 select 下拉列表过滤 html table 列

filtering html table columns with select dropdowns

我正在尝试制作一个 table 可以根据其中的值过滤每一列。我希望每个下拉列表只与列相关联,所以就像第一个下拉列表只查看第一列一样。我发现 javascript 代码可以完美运行,但前提是其中的每个值都是唯一的。在每个 row/column 中,我的 table 大多只是 yes/no,我认为我找到的代码不能按我想要的方式工作的原因是因为这些值不是唯一的。 OK/NO 的第一列有效,但在指定 yes/no 时查看其他列时会出现问题。如果我 select 好的,不,是的,从 3 个下拉列表中它应该只显示第一行,但它也显示第三行。第一行可以,不,是,第三行可以,不,不。所以问题是,在第三行的第三列中它不是,但是在从第三个下拉列表中指定是之后它仍然出现。有没有办法让下拉列表只查看特定的列?我仍然是 javascript 的初学者,所以我只是希望看看是否有人可以提供帮助,同时我还在其他来源中进行调查。

这里是 html

<select class="filter">
    <option value="">None</option>
    <option value="a">OK</option>
    <option value="b">NO</option>
</select>
<select class="filter">
    <option value="">None</option>
    <option value="1">no</option>
    <option value="2">yes</option>
    
</select>
<select class="filter">
    <option value="">None</option>
    <option value="3">no</option>
    <option value="4">yes</option>
    
</select>
<table>
    <tbody>
    <tr>
      <th>Status</th>
      <th>Cough</th>
      <th>Fever</th>
    </tr>
        <tr>
            <td>OK</td>
            <td>no</td>
            <td>yes</td>
        </tr>
        <tr>
            <td>NO</td>
            <td>yes</td>
            <td>yes</td>
        </tr>
        <tr>
            <td>OK</td>
            <td>no</td>
            <td>no</td>
        </tr>
        <tr>
            <td>NO</td>
            <td>yes</td>
            <td>no</td>
        </tr>
    </tbody>
</table>

这是我在网上找到的javascript代码

$(document).ready(function () {

    $('.filter').change(function () {
        var values = [];
        $('.filter option:selected').each(function () {
            if ($(this).val() != "") values.push($(this).text());
        });
        filter('table > tbody > tr', values);
    });

    function filter(selector, values) {
        $(selector).each(function () {
            var sel = $(this);
            var tokens = sel.text().split('\n');
            var toknesObj = [], i;
            for(i=0;i<tokens.length;i++){
                toknesObj.push( {text:tokens[i].trim(), found:false});
            }

            var show = false;
            console.log(values);
            $.each(values, function (i, val) {
                
                for(i=0;i<toknesObj.length;i++){                    
                    if (!toknesObj[i].found && toknesObj[i].text.search(new RegExp("\b"+val+"\b")) >= 0) {
                        toknesObj[i].found = true;
                    }
                }
            });          
            
            var count = 0;
             $.each(toknesObj, function (i, val) {
                 if (val.found){
                     count+=1;
                 }
             });
            show = (count === values.length);        
            show ? sel.show() : sel.hide();
        });
    }
});

这里是link原来的javascript代码http://jsfiddle.net/lukaszewczak/2dhE5/52/

您可以通过引入一些东西来过滤 table 数据:

  1. 跟踪过滤器选择的过滤器状态
  2. 每个过滤器的数据属性以识别它们
  3. 确保过滤器的值与数据文本完全匹配

const
  table = document.querySelector('.filter-table'),
  filterState = {};

const dataFromRow = (row, headers) =>
  Object.fromEntries([...row.querySelectorAll('td')]
    .map((td, index) => [headers[index], td.textContent]));

const matchesCriteria = (rowData, filters) =>
  filters.every(([key, value]) => rowData[key] === value);

const refresh = () => {
  const
    headers = [...table.querySelectorAll('thead th')].map(th => th.textContent),
    filters = Object.entries(filterState),
    showAll = filters.length === 0;
  table.querySelectorAll('tbody tr').forEach(row => {
    const show = showAll || matchesCriteria(dataFromRow(row, headers), filters);
    row.classList.toggle('hidden-row', !show);
  });
};

const handleFilterChange = (e) => {
  const
    field = e.target.dataset.field,
    value = e.target.value;
  if (value) { filterState[field] = value; }
  else { delete filterState[field]; }
  refresh();
};

document.querySelectorAll('.filter').forEach(filter =>
  filter.addEventListener('change', handleFilterChange));
.filter-table {
  border-collapse: collapse;
}

.filter-table {
  border: thin solid grey;
}

.filter-table thead {
  border-bottom: thin solid grey;
}

.filter-table th, .filter-table td {
  padding: 0.25em 0.5em;
}

.filter-table th {
  background: #CCC;
}

.filter-table tbody tr:nth-child(even) {
  background: #EEE;
}

.hidden-row {
  display: none;
}
<select class="filter" data-field="Status">
  <option value="">None</option>
  <option value="OK">OK</option>
  <option value="NO">NO</option>
</select>
<select class="filter" data-field="Cough">
  <option value="">None</option>
  <option value="No">No</option>
  <option value="Yes">Yes</option>
</select>
<select class="filter" data-field="Fever">
  <option value="">None</option>
  <option value="No">No</option>
  <option value="Yes">Yes</option>
</select>
<hr />
<table class="filter-table">
  <thead>
    <tr><th>Status</th><th>Cough</th><th>Fever</th></tr>
  </thead>
  <tbody>
    <tr><td>OK</td><td>No</td><td>Yes</td></tr>
    <tr><td>NO</td><td>Yes</td><td>Yes</td></tr>
    <tr><td>OK</td><td>No</td><td>No</td></tr>
    <tr><td>NO</td><td>Yes</td><td>No</td></tr>
  </tbody>
</table>


如果您希望过滤器位于 headers 中,您可以将 <select> 元素移动到 <th> 中另一个 <tr> 中的 <thead> 中=].

const
  table = document.querySelector('.filter-table'),
  filterState = {};

const dataFromRow = (row, headers) =>
  Object.fromEntries([...row.querySelectorAll('td')]
    .map((td, index) => [headers[index], td.textContent]));

const matchesCriteria = (rowData, filters) =>
  filters.every(([key, value]) => rowData[key] === value);

const refresh = () => {
  const
    headers = [...table.querySelectorAll('thead th')].map(th => th.textContent),
    filters = Object.entries(filterState),
    showAll = filters.length === 0;
  table.querySelectorAll('tbody tr').forEach(row => {
    const show = showAll || matchesCriteria(dataFromRow(row, headers), filters);
    row.classList.toggle('hidden-row', !show);
  });
};

const handleFilterChange = (e) => {
  const
    field = e.target.dataset.field,
    value = e.target.value;
  if (value) {
    filterState[field] = value;
  } else {
    delete filterState[field];
  }
  refresh();
};

document.querySelectorAll('.filter').forEach(filter =>
  filter.addEventListener('change', handleFilterChange));
.filter-table {
  border-collapse: collapse;
}

.filter-table {
  border: thin solid grey;
}

.filter-table thead {
  border-bottom: thin solid grey;
}

.filter-table th,
.filter-table td {
  padding: 0.25em 0.5em;
}

.filter-table th {
  background: #CCC;
}

.filter-table tbody tr:nth-child(even) {
  background: #EEE;
}

.hidden-row {
  display: none;
}
<table class="filter-table">
  <thead>
    <tr>
      <th>Status</th>
      <th>Cough</th>
      <th>Fever</th>
    </tr>
    <tr>
      <th>
        <select class="filter" data-field="Status">
          <option value="">None</option>
          <option value="OK">OK</option>
          <option value="NO">NO</option>
        </select>
      </th>
      <th>
        <select class="filter" data-field="Cough">
          <option value="">None</option>
          <option value="No">No</option>
          <option value="Yes">Yes</option>
        </select>
      </th>
      <th>
        <select class="filter" data-field="Fever">
          <option value="">None</option>
          <option value="No">No</option>
          <option value="Yes">Yes</option>
        </select>
      </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>OK</td>
      <td>No</td>
      <td>Yes</td>
    </tr>
    <tr>
      <td>NO</td>
      <td>Yes</td>
      <td>Yes</td>
    </tr>
    <tr>
      <td>OK</td>
      <td>No</td>
      <td>No</td>
    </tr>
    <tr>
      <td>NO</td>
      <td>Yes</td>
      <td>No</td>
    </tr>
  </tbody>
</table>