Ali Kakakhel
Ali Kakakhel

Reputation: 193

filtering table columns based on multiple input fields

Task

I have a table with multiple columns. Each column has an input field above it. I want to filter each row such that the table shows any rows that have at least one column that contains the value in the input field above the column.

Issue

When I try typing in values into the input fields, the table does not filter. I am not sure where my error is. Since I am still very much in the learning phase, any tips for syntax or performance would also be appreciated. The following minimally (not-yet) working example is the best I could do based on various answers on this website.

Code

function performReset() {
  document.getElementById("inputName").value = "";
  document.getElementById("inputCity").value = "";
  document.getElementById("inputCountry").value = "";
  filterTable();
}

function filterTable() {
  // Get the table rows.
  let rows = document.querySelector("#myTable > tbody").rows;

  // Get the inputed values to filter against.
  let inputedName = document.getElementById("inputName").value.toUpperCase();
  let inputedCity = document.getElementById("inputCity").value.toUpperCase();
  let inputedCountry = document.getElementById("inputCountry").value.toUpperCase();

  // Loop over the rows to perform the filter.
  let totalRows = rows.length;
  for (let i = 0; i < totalRows; i++) {
    // Get the contents of the relevant cell data.
    let rowName = rows[i].cells[0].textContent.toUpperCase();
    let rowCity = rows[i].cells[1].textContent.toUpperCase();
    let rowCountry = rows[i].cells[2].textContent.toUpperCase();

    // Define an array of conditions.
    // Note: the conditions are evaluated here.
    let conditionsArray = [
      rowName.indexOf(inputedName) > -1,
      rowCity.indexOf(inputedCity) > -1,
      rowCountry.indexOf(inputedCountry) > -1
    ];

    // If any of the above conditions are true then show the row,
    // otherwise turn of displaying that row.
    if (conditionsArray.indexOf(true) > -1) {
      rows[i].display = "";
    } else {
      rows[i].display = "none";
    }
  }
}
<link href="https://www.w3schools.com/w3css/4/w3.css" rel="stylesheet" />
<h2 class="w3-center">Filter Table Test</h2>

<p class="w3-center"><button id="buttonReset" onclick="performReset()" class="w3-button w3-grey w3-hover-light-grey">Reset</button></p>

<table id="myTable" class="w3-table w3-striped w3-hoverable">
  <!--Inputs Used For Filtering-->
  <tr>
    <td><input id="inputName" onkeyup="filterTable()" class="w3-input" placeholder="Name..."></td>
    <td><input id="inputCity" onkeyup="filterTable()" class="w3-input" placeholder="City..."></td>
    <td><input id="inputCountry" onkeyup="filterTable()" class="w3-input" placeholder="Country..."></td>
  </tr>
  <!--Column Headings-->
  <tr class="w3-dark-grey">
    <th>Customer</th>
    <th>City</th>
    <th>Country</th>
  </tr>
  <!--Row Data-->
  <tbody>
    <tr class="item">
      <td>Alfreds Futterkiste</td>
      <td>Berlin</td>
      <td>Germany</td>
    </tr>
    <tr class="item">
      <td>Berglunds snabbköp</td>
      <td>Lule </td>
      <td>Sweden</td>
    </tr>
    <tr class="item">
      <td>Centro comercial Moctezuma</td>
      <td>México D.F.</td>
      <td>Mexico</td>
    </tr>
    <tr class="item">
      <td>Ernst Handel</td>
      <td>Graz</td>
      <td>Austria</td>
    </tr>
    <tr class="item">
      <td>FISSA Fabrica Inter. Salchichas S.A.</td>
      <td>Madrid</td>
      <td>Spain</td>
    </tr>
    <tr class="item">
      <td>Galería del gastrónomo</td>
      <td>Barcelona</td>
      <td>Spain</td>
    </tr>
    <tr class="item">
      <td>Island Trading</td>
      <td>Cowes</td>
      <td>UK</td>
    </tr>
    <tr class="item">
      <td>Königlich Essen</td>
      <td>Brandenburg</td>
      <td>Germany</td>
    </tr>
    <tr class="item">
      <td>Laughing Bacchus Wine Cellars</td>
      <td>Vancouver</td>
      <td>Canada</td>
    </tr>
    <tr class="item">
      <td>Magazzini Alimentari Riuniti</td>
      <td>Bergamo</td>
      <td>Italy</td>
    </tr>
    <tr class="item">
      <td>North/South</td>
      <td>London</td>
      <td>UK</td>
    </tr>
    <tr class="item">
      <td>Paris spécialités</td>
      <td>Paris</td>
      <td>France</td>
    </tr>
    <tr class="item">
      <td>Rattlesnake Canyon Grocery</td>
      <td>Albuquerque</td>
      <td>USA</td>
    </tr>
    <tr class="item">
      <td>Simons bistro</td>
      <td>København</td>
      <td>Denmark</td>
    </tr>
    <tr class="item">
      <td>The Big Cheese</td>
      <td>Portland</td>
      <td>USA</td>
    </tr>
    <tr class="item">
      <td>Vaffeljernet</td>
      <td>Århus</td>
      <td>Denmark</td>
    </tr>
    <tr class="item">
      <td>Wolski Zajazd</td>
      <td>Warszawa</td>
      <td>Poland</td>
    </tr>
  </tbody>
</table>

Edit 1: Modified document.querySelector('#myTable tbody') to document.querySelector('#myTable > tbody'). But my issue persists.

Upvotes: 0

Views: 8130

Answers (2)

Mamun
Mamun

Reputation: 68923

You can attach the filter function to the event of all the input elements by passing the event and specific index.

Try the following way:

function performReset() {
  document.getElementById("inputName").value = "";
  document.getElementById("inputCity").value = "";
  document.getElementById("inputCountry").value = "";
  filterTable(event, 0);
}

function filterTable(event, index) {
  var filter = event.target.value.toUpperCase();
  var rows = document.querySelector("#myTable tbody").rows;
  for (var i = 0; i < rows.length; i++) {
    var firstCol = rows[i].cells[0].textContent.toUpperCase();
    var secondCol = rows[i].cells[1].textContent.toUpperCase();
    var thirdCol = rows[i].cells[2].textContent.toUpperCase();
    if ((firstCol.indexOf(filter) > -1 && index == 0) || (secondCol.indexOf(filter) > -1 && index == 1) || (thirdCol.indexOf(filter) > -1 && index == 2)) {
      rows[i].style.display = "";
    } else {
      rows[i].style.display = "none";
    }      
  }
}

document.querySelectorAll('input.w3-input').forEach(function(el,idx){
  el.addEventListener('keyup', function(e){
    filterTable(e, idx);
  }, false);
});
<link href="https://www.w3schools.com/w3css/4/w3.css" rel="stylesheet" />
<h2 class="w3-center">Filter Table Test</h2>

<p class="w3-center"><button id="buttonReset" onclick="performReset()" class="w3-button w3-grey w3-hover-light-grey">Reset</button></p>

<table id="myTable" class="w3-table w3-striped w3-hoverable">
  <!--Column Headings-->
  <thead>
    <tr>
      <td><input id="inputName" class="w3-input" placeholder="Name..."></td>
      <td><input id="inputCity" class="w3-input" placeholder="City..."></td>
      <td><input id="inputCountry" class="w3-input" placeholder="Country..."></td>
    </tr>
  </thead>
  <!--Row Data-->
  <tbody>
    <tr class="item">
      <td>Alfreds Futterkiste</td>
      <td>Berlin</td>
      <td>Germany</td>
    </tr>
    <tr class="item">
      <td>Berglunds snabbköp</td>
      <td>Lule </td>
      <td>Sweden</td>
    </tr>
    <tr class="item">
      <td>Centro comercial Moctezuma</td>
      <td>México D.F.</td>
      <td>Mexico</td>
    </tr>
    <tr class="item">
      <td>Ernst Handel</td>
      <td>Graz</td>
      <td>Austria</td>
    </tr>
    <tr class="item">
      <td>FISSA Fabrica Inter. Salchichas S.A.</td>
      <td>Madrid</td>
      <td>Spain</td>
    </tr>
    <tr class="item">
      <td>Galería del gastrónomo</td>
      <td>Barcelona</td>
      <td>Spain</td>
    </tr>
    <tr class="item">
      <td>Island Trading</td>
      <td>Cowes</td>
      <td>UK</td>
    </tr>
    <tr class="item">
      <td>Königlich Essen</td>
      <td>Brandenburg</td>
      <td>Germany</td>
    </tr>
    <tr class="item">
      <td>Laughing Bacchus Wine Cellars</td>
      <td>Vancouver</td>
      <td>Canada</td>
    </tr>
    <tr class="item">
      <td>Magazzini Alimentari Riuniti</td>
      <td>Bergamo</td>
      <td>Italy</td>
    </tr>
    <tr class="item">
      <td>North/South</td>
      <td>London</td>
      <td>UK</td>
    </tr>
    <tr class="item">
      <td>Paris spécialités</td>
      <td>Paris</td>
      <td>France</td>
    </tr>
    <tr class="item">
      <td>Rattlesnake Canyon Grocery</td>
      <td>Albuquerque</td>
      <td>USA</td>
    </tr>
    <tr class="item">
      <td>Simons bistro</td>
      <td>København</td>
      <td>Denmark</td>
    </tr>
    <tr class="item">
      <td>The Big Cheese</td>
      <td>Portland</td>
      <td>USA</td>
    </tr>
    <tr class="item">
      <td>Vaffeljernet</td>
      <td>Århus</td>
      <td>Denmark</td>
    </tr>
    <tr class="item">
      <td>Wolski Zajazd</td>
      <td>Warszawa</td>
      <td>Poland</td>
    </tr>    
  </tbody>
</table>

Upvotes: 3

Ferdinando
Ferdinando

Reputation: 964

The @Mamun's answer is good and works. An other solution that i used is: i have used only one input tag for the three columns

you can try also this code

CSS:

<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://www.w3schools.com/w3css/4/w3.css" rel="stylesheet" />
<style>

* {
  box-sizing: border-box;
}

#myInput {
  background-image: url('/css/searchicon.png');
  background-position: 10px 10px;
  background-repeat: no-repeat;
  width: 100%;
  font-size: 16px;
  padding: 12px 20px 12px 40px;
  border: 1px solid #ddd;
  margin-bottom: 12px;
}

#myTable {
  border-collapse: collapse;
  width: 100%;
  border: 1px solid #ddd;
  font-size: 18px;
}

#myTable th, #myTable td {
  text-align: left;
  padding: 12px;
}

#myTable tr {
  border-bottom: 1px solid #ddd;
}

#myTable tr.header, #myTable tr:hover {
  background-color: #f1f1f1;
}
</style>
</head>

JAVASCRIPT:

<script>
  function performReset() {
  document.getElementById("myInput").value = "";
  filterTable();
}

function filterTable() {
  var input, filter, table, tr, i,name,country,city;
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  table = document.getElementById("myTable");
  tr = table.getElementsByTagName("tr");
  for (i = 0; i < tr.length; i++) {
    //write here which columns you want filter...
    name=tr[i].getElementsByTagName("td")[0];
    city=tr[i].getElementsByTagName("td")[1];
    country=tr[i].getElementsByTagName("td")[2];

    if (name) {
      if (name.innerHTML.toUpperCase().indexOf(filter) > -1 ||city.innerHTML.toUpperCase().indexOf(filter) > -1 || country.innerHTML.toUpperCase().indexOf(filter) > -1) {
        tr[i].style.display = "";
      } else {
        tr[i].style.display = "none";
      }
    }
  }
}
</script>

HTML:

<body>
<p class="w3-center"><button id="buttonReset" onclick="performReset()" class="w3-button w3-grey w3-hover-light-grey">Reset</button></p>

<h2>My Customers</h2>

<input type="text" id="myInput" onkeyup="filterTable()" placeholder="Search for names.." title="Type in a name">

<table id="myTable">
  <tr class="header">
    <th style="width:60%;">Name</th>
    <th style="width:20%;">City</th>
    <th style="width:20%;">Country</th>
  </tr>
  <tbody>
  <tr class="item">
    <td>Alfreds Futterkiste</td>
    <td>Berlin</td>
    <td>Germany</td>
  </tr>
  <tr class="item">
    <td>Berglunds snabbköp</td>
    <td>Lule </td>
    <td>Sweden</td>
  </tr>
  <tr class="item">
    <td>Centro comercial Moctezuma</td>
    <td>México D.F.</td>
    <td>Mexico</td>
  </tr>
  <tr class="item">
    <td>Ernst Handel</td>
    <td>Graz</td>
    <td>Austria</td>
  </tr>
  <tr class="item">
    <td>FISSA Fabrica Inter. Salchichas S.A.</td>
    <td>Madrid</td>
    <td>Spain</td>
  </tr>
  <tr class="item">
    <td>Galería del gastrónomo</td>
    <td>Barcelona</td>
    <td>Spain</td>
  </tr>
  <tr class="item">
    <td>Island Trading</td>
    <td>Cowes</td>
    <td>UK</td>
  </tr>
  <tr class="item">
    <td>Königlich Essen</td>
    <td>Brandenburg</td>
    <td>Germany</td>
  </tr>
  <tr class="item">
    <td>Laughing Bacchus Wine Cellars</td>
    <td>Vancouver</td>
    <td>Canada</td>
  </tr>
  <tr class="item">
    <td>Magazzini Alimentari Riuniti</td>
    <td>Bergamo</td>
    <td>Italy</td>
  </tr>
  <tr class="item">
    <td>North/South</td>
    <td>London</td>
    <td>UK</td>
  </tr>
  <tr class="item">
    <td>Paris spécialités</td>
    <td>Paris</td>
    <td>France</td>
  </tr>
  <tr class="item">
    <td>Rattlesnake Canyon Grocery</td>
    <td>Albuquerque</td>
    <td>USA</td>
  </tr>
  <tr class="item">
    <td>Simons bistro</td>
    <td>København</td>
    <td>Denmark</td>
  </tr>
  <tr class="item">
    <td>The Big Cheese</td>
    <td>Portland</td>
    <td>USA</td>
  </tr>
  <tr class="item">
    <td>Vaffeljernet</td>
    <td>Århus</td>
    <td>Denmark</td>
  </tr>
  <tr class="item">
    <td>Wolski Zajazd</td>
    <td>Warszawa</td>
    <td>Poland</td>
  </tr>
  </tbody>
</table>
</body>

ALL the (SNIPPET)code :

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://www.w3schools.com/w3css/4/w3.css" rel="stylesheet" />
<style>
  
* {
  box-sizing: border-box;
}

#myInput {
  background-image: url('/css/searchicon.png');
  background-position: 10px 10px;
  background-repeat: no-repeat;
  width: 100%;
  font-size: 16px;
  padding: 12px 20px 12px 40px;
  border: 1px solid #ddd;
  margin-bottom: 12px;
}

#myTable {
  border-collapse: collapse;
  width: 100%;
  border: 1px solid #ddd;
  font-size: 18px;
}

#myTable th, #myTable td {
  text-align: left;
  padding: 12px;
}

#myTable tr {
  border-bottom: 1px solid #ddd;
}

#myTable tr.header, #myTable tr:hover {
  background-color: #f1f1f1;
}
</style>
</head>
<body>
<p class="w3-center"><button id="buttonReset" onclick="performReset()" class="w3-button w3-grey w3-hover-light-grey">Reset</button></p>

<h2>My Customers</h2>

<input type="text" id="myInput" onkeyup="filterTable()" placeholder="Search for names.." title="Type in a name">

<table id="myTable">
  <tr class="header">
    <th style="width:60%;">Name</th>
    <th style="width:20%;">City</th>
    <th style="width:20%;">Country</th>
  </tr>
  <tbody>
  <tr class="item">
    <td>Alfreds Futterkiste</td>
    <td>Berlin</td>
    <td>Germany</td>
  </tr>
  <tr class="item">
    <td>Berglunds snabbköp</td>
    <td>Lule </td>
    <td>Sweden</td>
  </tr>
  <tr class="item">
    <td>Centro comercial Moctezuma</td>
    <td>México D.F.</td>
    <td>Mexico</td>
  </tr>
  <tr class="item">
    <td>Ernst Handel</td>
    <td>Graz</td>
    <td>Austria</td>
  </tr>
  <tr class="item">
    <td>FISSA Fabrica Inter. Salchichas S.A.</td>
    <td>Madrid</td>
    <td>Spain</td>
  </tr>
  <tr class="item">
    <td>Galería del gastrónomo</td>
    <td>Barcelona</td>
    <td>Spain</td>
  </tr>
  <tr class="item">
    <td>Island Trading</td>
    <td>Cowes</td>
    <td>UK</td>
  </tr>
  <tr class="item">
    <td>Königlich Essen</td>
    <td>Brandenburg</td>
    <td>Germany</td>
  </tr>
  <tr class="item">
    <td>Laughing Bacchus Wine Cellars</td>
    <td>Vancouver</td>
    <td>Canada</td>
  </tr>
  <tr class="item">
    <td>Magazzini Alimentari Riuniti</td>
    <td>Bergamo</td>
    <td>Italy</td>
  </tr>
  <tr class="item">
    <td>North/South</td>
    <td>London</td>
    <td>UK</td>
  </tr>
  <tr class="item">
    <td>Paris spécialités</td>
    <td>Paris</td>
    <td>France</td>
  </tr>
  <tr class="item">
    <td>Rattlesnake Canyon Grocery</td>
    <td>Albuquerque</td>
    <td>USA</td>
  </tr>
  <tr class="item">
    <td>Simons bistro</td>
    <td>København</td>
    <td>Denmark</td>
  </tr>
  <tr class="item">
    <td>The Big Cheese</td>
    <td>Portland</td>
    <td>USA</td>
  </tr>
  <tr class="item">
    <td>Vaffeljernet</td>
    <td>Århus</td>
    <td>Denmark</td>
  </tr>
  <tr class="item">
    <td>Wolski Zajazd</td>
    <td>Warszawa</td>
    <td>Poland</td>
  </tr>
  </tbody>
</table>

<script>
  function performReset() {
  document.getElementById("myInput").value = "";
  filterTable();
}

function filterTable() {
  var input, filter, table, tr, i,name,country,city;
  input = document.getElementById("myInput");
  filter = input.value.toUpperCase();
  table = document.getElementById("myTable");
  tr = table.getElementsByTagName("tr");
  for (i = 0; i < tr.length; i++) {
    //write here which column you want filter
    name=tr[i].getElementsByTagName("td")[0];
    city=tr[i].getElementsByTagName("td")[1];
    country=tr[i].getElementsByTagName("td")[2];

    if (name) {
      if (name.innerHTML.toUpperCase().indexOf(filter) > -1 ||city.innerHTML.toUpperCase().indexOf(filter) > -1 || country.innerHTML.toUpperCase().indexOf(filter) > -1) {
        tr[i].style.display = "";
      } else {
        tr[i].style.display = "none";
      }
    }
  }
}
</script>

</body>
</html>

Upvotes: 0

Related Questions