2

I use this code to hide all rows in a table that have a td with a class named "hide". This is working fine.

$('.table').find('tr:has(td.hide)').hide();

Now I am trying to hide all all rows in table if the row has n number of td with the class equal to hide. I was not even able to loop on the tr list of the table with thos code

$('.table  > tr').each(function() {
console.log("new tr", $(this).text());
});

my html looks as following

    <table class='table'>
    <tr class='hidable'><td class='hide'> Some text</td> <td class='hide'> Some text</td></tr>

    <tr class='hidable'><td class='hide'> Some text</td> <td class='nothide'> Some text</td></tr>
</table>

in this example i want to hide the row if the two tds have the class hide.

yalpsid
  • 21
  • 2

3 Answers3

2

When you create a table without tbody, that tag is automatically generated.

Child combinator:

Elements matched by the second selector must be the immediate children of the elements matched by the first selector.

Include tbody as part of the selector. Try $('.table tbody > tr')

$('.table tbody > tr').each(function() {
  console.log("new tr", $(this).text());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class='table'>
  <tr class='hidable'>
    <td> Some text </td>
    <td class='hide'> Some text</td> 
    <td class='hide'> Some text</td>
  </tr>
  <tr>
    <td class='nothide'> Some text</td>
  </tr>
</table>

OR: Remove > from the selector

$('.table tr').each(function() {
  console.log("new tr", $(this).text());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class='table'>
  <tr class='hidable'>
    <td> Some text </td>
    <td class='hide'> Some text</td> 
    <td class='hide'> Some text</td>
  </tr>
  <tr>
    <td class='nothide'> Some text</td>
  </tr>
</table>
Mamun
  • 66,969
  • 9
  • 47
  • 59
1

With jQuery I'd suggest using toggleClass():

// here we select the <tr> elements, and chain the toggleClass() method
// to that jQuery collection:
$('tr').toggleClass(function() {
  // within the anonymous function 'this' refers to the current <tr>
  // element of the collection (the native DOM node not a jQuery $(this))
  // we use Element.querySelectorAll() to retrieve all the <td> elements
  // with a class of 'hide' and then test the length to see if there
  // are more than one. If this is true, we return the 'hideRow' class
  // to the method, otherwise we return an empty string. Obviously this
  // approach uses a CSS selector ('hideRow') to hide the relevant <tr>
  // elements:
  return this.querySelectorAll('.hide').length > 1 ? 'hideRow' : '';
});
.hide {
  background-color: limegreen;
  opacity: 0.5;
}

.hideRow {
  /* here we use opacity: 0.5 so that you can visually
     see which elements are selected/affected; in production
     you should obviously switch to 'display: none' to hide the
     elements: */
  opacity: 0.5;
}
<table>
  <tbody>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td>cell 3</td>
      <td class="hide">cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td class="hide">cell 2</td>
      <td>cell 3</td>
      <td class="hide">cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td class="hide">cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td class="hide">cell 1</td>
      <td class="hide">cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td class="hide">cell 1</td>
      <td class="hide">cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
  </tbody>
</table>

JS Fiddle demo.

In native JavaScript — using a contemporary browser — the following would achieve the same thing:

// here we use the spread syntax to conver the iterable NodeList returned by
// document.querySelectorAll() into an Array, we then iterate over that Array
// of Nodes using Array.prototype.forEach():
[...document.querySelectorAll('tr')].forEach(
  // we use an anonymous Arrow function - as we don't need to use 'this' - in
  // order perform a function on each of the <tr> elements of the Array of
  // <tr> elements; the 'tr' passed into the function is a reference to the
  // current <tr>:
  (tr) => {
    // here we use the Element.classList API, with its toggle() method to
    // supply a class-name ('hideRow'), and we use the assessment to determin
    // whether or not the class-name should be applied. If the assessment
    // evaluates to true then the class-name is applied, if false it is not:
    tr.classList.toggle('hideRow', tr.querySelectorAll('.hide').length > 1);
  });
.hide {
  background-color: limegreen;
  opacity: 0.5;
}

.hideRow {
  opacity: 0.5;
}
<table>
  <tbody>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td>cell 3</td>
      <td class="hide">cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td class="hide">cell 2</td>
      <td>cell 3</td>
      <td class="hide">cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td class="hide">cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td class="hide">cell 1</td>
      <td class="hide">cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td class="hide">cell 1</td>
      <td class="hide">cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
    <tr>
      <td>cell 1</td>
      <td>cell 2</td>
      <td>cell 3</td>
      <td>cell 4</td>
    </tr>
  </tbody>
</table>

JS Fiddle demo.

As an important addenda to my original answer, the reason that your selector:

$('.table  > tr')

doesn't work is because of the child combinator, the >, which would cause jQuery to retrieve the <tr> elements which are children of the <table class=".table"> element. As browsers predictably rescue 'broken' HTML — though a <tbody> is not mandatory according to the spec — they will all automagically insert a <tbody> element to wrap any <tr> elements which are contained within a <table> that aren't already so wrapped.

This has been discussed elsewhere on the site: https://stackoverflow.com/a/5568877/82548

References:

David Thomas
  • 249,100
  • 51
  • 377
  • 410
0
  • You want to hide row if 2 td's have hide class , if this is your requirement then here is tested example

     $(".table tr").each(function(){ 
          if($(this).find("td.hide").length == 2) { 
             $(this).hide(); 
          } 
      });
    

Here I loop through each tr and then in each tr I check all td with class "hide" with find("td.hide").length == 2 and if length is equal to two then hide the row.

mohitesachin217
  • 451
  • 5
  • 14