Srpic
Srpic

Reputation: 450

Remove custom table filter based on input value

I have a JS function that filters data for me based on a drop-down menu, which has all values from table and it works just fine.

I would like to have an 'All' value and if users select the value, it will show all values/remove the filter.

The below function does not work, it shows nothing if I select "All". Could you advise me, how to achieve this, please?

/* Drop-down function */
function categoriesFilter() {
  var input, filter, table, tr, td, i;
  input = document.getElementById("categories");
  filter = input.value.toUpperCase();
  table = document.getElementById("repositoryReports");
  tr = table.getElementsByTagName("tr");
  if (filter != "All") {
    for (i = 0; i < tr.length; i++) {
      td = tr[i].getElementsByTagName("td")[0];
      if (td) {
        if (td.innerText.toUpperCase().indexOf(filter) > -1) {
          tr[i].style.display = "";
        } else {
          tr[i].style.display = "none";
        }
      }
    }
  }
}
<body>
  <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
  <table id="repositoryReports" class="repository-table">
    <tr>
      <th>Category<br><br>
        <select class="drop-down" id="categories" onchange="categoriesFilter()">
          <option>All</option>
          <option>1</option>
          <option>2</option>
          <option>3</option>
          <option>4</option>
          <option>5</option>
          <option>6</option>
          <option>7</option>
        </select>
      </th>
      <th>Name</th>
    </tr>
    <tr>
      <td>1</td>
      <td>Test 1</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Test 2</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Test 3</td>
    </tr>
    <tr>
      <td>4</td>
      <td>Test 4</td>
    </tr>
    <tr>
      <td>5</td>
      <td>Test 5</td>
    </tr>
    <tr>
      <td>6</td>
      <td>Test 6</td>
    </tr>
    <tr>
      <td>7</td>
      <td>Test 7</td>
    </tr>
  </table>
</body>

Many thanks!

Upvotes: 1

Views: 209

Answers (2)

Rory McCrossan
Rory McCrossan

Reputation: 337691

To show all rows when the All option is selected you can simply adjust your if condition to check for that value when setting the rows to a visible state.

Note in the example below that I made some changes to the logic to make it more succinct and in line with modern standards, specifically removing the inline onchange attribute for an unobtrusive event handler.

let table = document.querySelector("#repositoryReports");
let rows = table.querySelectorAll("tbody tr");

document.querySelector('#categories').addEventListener('change', e => {
  let filter = e.target.value.toUpperCase();
  rows.forEach(tr => {
    let td = tr.querySelector('td'); // gets the first match only
    tr.style.display = (filter === "ALL" || (td && td.textContent.toUpperCase().includes(filter))) ? 'table-row' : 'none';
  });
});
<table id="repositoryReports" class="repository-table">
  <thead>
    <tr>
      <th>
        Category<br><br>
        <select class="drop-down" id="categories">
          <option>All</option>
          <option>1</option>
          <option>2</option>
          <option>3</option>
          <option>4</option>
          <option>5</option>
          <option>6</option>
          <option>7</option>
        </select>
      </th>
      <th>Name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>Test 1</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Test 2</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Test 3</td>
    </tr>
    <tr>
      <td>4</td>
      <td>Test 4</td>
    </tr>
    <tr>
      <td>5</td>
      <td>Test 5</td>
    </tr>
    <tr>
      <td>6</td>
      <td>Test 6</td>
    </tr>
    <tr>
      <td>7</td>
      <td>Test 7</td>
    </tr>
  </tbody>
</table>

Finally, this example assumes that the table content is static. If it gets dynamically updated you will need to move the table and rows variable definitions inside the change event handler.

Upvotes: 1

Laurens
Laurens

Reputation: 2607

First of all, you are capitalizing the filter, so you have to check for value ALL after that, not All. Secondly, you need to remove thee display style none when the filter ALL is used. Try the snippet below:

    /* Drop-down function */
    function categoriesFilter() {
        var input, filter, table, tr, td, i;
        input = document.getElementById("categories");
        filter = input.value.toUpperCase();
        table = document.getElementById("repositoryReports");
        tr = table.getElementsByTagName("tr");
            for (i = 0; i < tr.length; i++) {
            td = tr[i].getElementsByTagName("td")[0];
            if (td) {
                if (td.innerText.toUpperCase().indexOf(filter) > -1 || filter === "ALL") {
                tr[i].style.display = "";
                } else {
                tr[i].style.display = "none";
                }
            }       
            }
      }
<body>
  <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

<table id="repositoryReports" class="repository-table">
            <tr>
                <th>Category<br><br>
                    <select class="drop-down" id="categories" onchange="categoriesFilter()">
                        <option>All</option>
                        <option>1</option>
                        <option>2</option>
                        <option>3</option>
                        <option>4</option>
                        <option>5</option>
                        <option>6</option>
                        <option>7</option>
                    </select>
                </th>
                <th>Name</th>
            </tr>
            <tr>
                <td>1</td>
                <td>Test 1</td>
            </tr>
      <tr>
                <td>2</td>
                <td>Test 2</td>
            </tr>
             <tr>
                <td>3</td>
                <td>Test 3</td>
            </tr>
       <tr>
                <td>4</td>
                <td>Test 4</td>
            </tr>
       <tr>
                <td>5</td>
                <td>Test 5</td>
            </tr>
      <tr>
                <td>6</td>
                <td>Test 6</td>
            </tr>
      <tr>
                <td>7</td>
                <td>Test 7</td>
            </tr>
                
         </table>

</body>

Upvotes: 0

Related Questions