【问题标题】:filtering html table columns with select dropdowns使用选择下拉菜单过滤 html 表格列
【发布时间】:2021-07-03 11:14:48
【问题描述】:

我正在尝试制作一个可以根据其中的值过滤每一列的表格。我希望每个下拉列表仅与列相关联,因此第一个下拉列表仅查看第一列。我发现 javascript 代码可以完美运行,但前提是 中的每个值都是唯一的。我的表在每一行/列中大部分都是是/否,我认为我发现的代码不能按我想要的方式工作的原因是因为值不是唯一的。 OK/NO 的第一列有效,但在指定是/否时查看其他列时会出现问题。如果我从 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();
        });
    }
});

这里是原始javascript代码http://jsfiddle.net/lukaszewczak/2dhE5/52/的链接

【问题讨论】:

    标签: javascript html jquery filter html-table


    【解决方案1】:

    你可以通过引入一些东西来过滤表格数据:

    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>

    如果您希望过滤器位于标题中,您可以将 &lt;select&gt; 元素移动到 &lt;th&gt; 内的另一个 &lt;tr&gt;&lt;thead&gt; 内。

    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>

    【讨论】:

    • 我尝试使用方括号编辑器在本地 MAMP 服务器上运行代码,但由于某种原因 javascript 无法正常工作,您知道原因吗?
    • @mias 服务器和浏览器有什么关系(客户端代码)?
    • 没关系这个错误是我的错,它现在工作正常。感谢您的帮助!
    • 有没有办法将选择下拉菜单移动到表格标题中并且仍然可以使用 javascript?从选择的方式我可以看出它必须在表格之外。
    • @mias 将新的&lt;tr&gt; 添加到&lt;thead&gt; 并将每个选择放在&lt;th&gt; 中,以与初始标题行中的关联&lt;th&gt; 对齐。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    相关资源
    最近更新 更多