Jason
Jason

Reputation: 15335

Using jQuery .filter() to filter table for text by rows excluding a specific column

I have a table like

<input id="searchText" type="text" placeholder="Search...">
<table>
    <thead>
        <tr>
            <th>Col 1</th>
            <th>Col 2</th>
            <th>Col 3</th>
        </tr>
    </thead>
    <tbody id="tableData">
        <tr>
            <td class="action">Action</td>
            <td>something 1</td>
            <td>something 2</td>
        </tr>
        <tr>
            <td class="action">Action</td>
            <td>else 1</td>
            <td>else 2</td>
        </tr>
        <tr>
            <td class="action">Action</td>
            <td>action 1</td>
            <td>action 2</td>
        </tr>
    </tbody>
</table>

And I have some jQuery like:

    $("#searchText").on("keyup", function() {
        var value = $(this).val().toLowerCase();
        $("#tableData tr").filter(function() {
            $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1);
        });
    });

Fiddle here: https://jsfiddle.net/jreljac/4hfn0sqb/1/

I'd like the search to exclude the text in the first cell of each row. If someone were to type "action" it would filter the first two rows out leaving just the third row. Currently, nothing is filtered since "action" is in the first cell of each of the <tbody> rows.

I've tried several combinations of adding .not(".action") with no luck. Without using a plugin, is this possible?

Upvotes: 1

Views: 595

Answers (1)

Rory McCrossan
Rory McCrossan

Reputation: 337560

To achieve this you can use :gt(0) to ignore the text of the first column td cells:

$(this).toggle($(this).find('td:gt(0)').text().toLowerCase().indexOf(value) > -1);

Also note that you should be using each(), not filter(), here. This is because the former is used to loop. The latter is used to reduce the collection by a provided function, which you're not quite doing, and is not required here. Here's an updated full example:

$("#searchText").on("keyup", function() {
  var value = $(this).val().toLowerCase();
  
  $("#tableData tr").each(function() {
    var $tr = $(this);  
    $tr.toggle($tr.find('td:gt(0)').text().toLowerCase().indexOf(value) > -1);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="searchText" type="text" placeholder="Search...">
<table>
  <thead>
    <tr>
      <th>Col 1</th>
      <th>Col 2</th>
      <th>Col 3</th>
    </tr>
  </thead>
  <tbody id="tableData">
    <tr>
      <td>Action</td>
      <td>something 1</td>
      <td>something 2</td>
    </tr>
    <tr>
      <td>Action</td>
      <td>else 1</td>
      <td>else 2</td>
    </tr>
  </tbody>
</table>

If, for whatever reason, you still wanted to use filter(), then you'd need to restructure your logic like this; note the return and use of show() and hide():

$("#searchText").on("keyup", function() {
  var value = $(this).val().toLowerCase();
  
  $("#tableData tr").show().filter(function() {
    var $tr = $(this);  
    return $tr.find('td:gt(0)').text().toLowerCase().indexOf(value) == -1
  }).hide();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="searchText" type="text" placeholder="Search...">
<table>
  <thead>
    <tr>
      <th>Col 1</th>
      <th>Col 2</th>
      <th>Col 3</th>
    </tr>
  </thead>
  <tbody id="tableData">
    <tr>
      <td>Action</td>
      <td>something 1</td>
      <td>something 2</td>
    </tr>
    <tr>
      <td>Action</td>
      <td>else 1</td>
      <td>else 2</td>
    </tr>
  </tbody>
</table>

Upvotes: 2

Related Questions