Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

363
Vistas
Filter HTML Table using JavaScript - textContent Error

Desired Result: Input data from a .csv file into PHP. Take the data from the .csv file and store into an array. Store the array into an HTML table using PHP. Use a search engine to filter through the rows using JavaScript.

I am getting the following error in the JavaScript: Uncaught TypeError: Cannot read property 'textContent' of null

<script>  
const searchInput = document.getElementById("search");
const rows = document.querySelectorAll("tbody tr");
//console.log(rows);

searchInput.addEventListener("keyup", function (event) { 
    //console.log(event);
    const q = event.target.value.toLowerCase();
       rows.forEach(row => {
          //console.log(row);
        row.querySelector("td").textContent.toLowerCase().startsWith(q); 
        ? (row.style.display = "table-row")
        : (row.style.display = "none");
    } );
});
 </script> 

Using the console.log, I have been able to determine it is reading and looping through each row in the table correctly, but it is unable to loop through the 'td' to determine if it matches text in the search engine.

The Array is a NodeList when consoling out the rows if that information is useful.

Happy to upload more information if needed. Thank you for your help in advance!

EDIT Adding in minimal HTML. The table contains 15 rows, but for the purposes of this, only adding in a few. This table is creating from an array using PHP.

EDIT 2 Headers added into thead

<html>
<head>  
</head> 
    <body>   
    <input type="text" name="search" id="search" placeholder="Search for services..">
    <table>
<thead>
    <tr>
    <th>Item #</th>
    <th>Name</th>
    <th>Type</th>
    <th>Make</th>
    <th>Model</th>
    <th>Brand</th>
    <th>Description</th>
    </tr>
</thead>
<tbody>
    <tr>
    <td>1</td><td>Cut &amp; Blow Dry</td>
    <td>Service</td>
    <td></td>
    <td></td>
    <td>Hair by Cass</td>
    <td>Haircut and style after</td>
    </tr>
    </tbody>
</table>
    </body>
    </html>
over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

  • Your HTML table markup is not correct. The row with the <th>s should go in <thead> not in <tbody>
  • You're using invalid ternary operator syntax ; ? x : y.
  • Use rather the "input" event to account for mouse copy/paste stuff etc.

searchInput.addEventListener("input", function(evt) {
  const q = evt.currentTarget.value.toLowerCase();
  rows.forEach(row => {
    const matches = row.querySelector("td").textContent.toLowerCase().startsWith(q);
    row.style.display = matches ? "table-row" : "none";
  });
});

But keep in mind that row.querySelector("td") will only get the first TD in a row (not all of them):

Match for multiple cells using Array.prototype.some()

Here's an example that will allow you to search throughout any cell, and uses a better solution for the toggling by using Element.classList.toggle() (and .includes() instead of .startsWith())

const EL_search = document.querySelector("#search");
const ELS_rows = document.querySelectorAll("tbody tr");

EL_search.addEventListener("input", function(evt) {
  const q = evt.currentTarget.value.toLowerCase();
  ELS_rows.forEach(TR => {
    const TDS = TR.querySelectorAll("td");
    const matches = [...TDS].some(TD =>TD.textContent.toLowerCase().includes(q));
    TR.classList.toggle("none", !matches);
  });
});
.none {
  display: none;
}
<input type="text" id="search" autocomplete="off">

<table>
  <thead>
    <tr><th>Name</th><th>Surname</th></tr>
  </thead>
  <tbody>
    <tr><td>Ann</td><td>Doe</td></tr>
    <tr><td>Jon</td><td>Doe</td></tr>
    <tr><td>Jonas</td><td>Foe</td></tr>
  </tbody>
</table>

over 4 years ago · Santiago Trujillo Denunciar

0

The error comes from row.querySelector("td") because it's trying find td in the headers tr element which only contain th children.

The fix is simple, check if td was found before proceeding:

const td = row.querySelector("td");
if (!td)
  return;

td.textContent.toLowerCase().startsWith(q) ?
  (row.style.display = "table-row") :
  (row.style.display = "none");

Also, querySelector will only return first found element, if you need find all elements, use querySelectorAll which will return list of elements, and than use for loop to process all elements in the list.

const tds = row.querySelectorAll("td");

for(let i = 0; i < tds.length; i++)
{
  tds[i].textContent.toLowerCase().startsWith(q) ?
    (row.style.display = "table-row") :
    (row.style.display = "none");
}
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda