krishnet
krishnet

Reputation:

How to display count of child record in parent using Javascript or JQuery

<html>
<head>
    <script src="some.js" type="text/javascript"></script>
    <script type="text/javascript">
        //javascript-jquery code
    </script>
</head>
<body>
    <table>
        <tr id="parent_1">
            <td>Parent 1</td>
        </tr>
        <tr class="child">
            <td>Child 1</td>
        </tr>
        <tr class="child">
            <td>Child 2</td>
        </tr>
        <tr id="parent_2">
            <td>Parent2</td>
        </tr>
    </table>
</body>
</html>

I wanted "Parent 1" text to change to "Parent 1(2)" where '2' is the number of children for the given parent using Javascript or Jquery. How is this possible?

Upvotes: 1

Views: 4394

Answers (4)

bobince
bobince

Reputation: 536735

I'm finding the complex jQuery selectors and loops quite amusing, given that the DOM already has a perfectly good ‘rowIndex’ property you can use to grab the number of children simply and much more efficiently:

var p1= document.getElementById('parent_1');
var p2= document.getElementById('parent_2');

var childn= p2.rowIndex-p1.rowIndex-1;
p1.cells[0].firstChild.data+= ' ('+childn+')';

Upvotes: 0

Paolo Bergantino
Paolo Bergantino

Reputation: 488714

Mmm. Tough one. :) This should do it, though:

$(function() {
    $("tr[id^='parent_']").each(function() {
        var count = 0;
        $(this).nextAll('tr').each(function() {
            if($(this).hasClass('child')) {
                count++;
            } else {
                return false;
            }
        });
        $(this).find('td').append(' (' + count + ')');
    });
});

Tested and works.


Although the above works, it is not very efficient. I also want to take a second to suggest you change the format of your HTML a little bit. You want to make your code be as semantically relevant to the content it holds as possible. Having one huge table mixing parents and childs is not the optimal way of achieving this. I am not sure what your use case is here, but consider doing something like this:

<ul>
  <li id="parent_1">
    <span>Parent 1</span>
    <ul>
      <li>Children 1</li> 
      <li>Children 2</li>
      <li>Children 3</li>
    </ul>
  </li>
  <li id="parent_2">
    <span>Parent 2</span>
    <ul>
      <li>Children 1</li> 
    </ul>
  </li>
  <li id="parent_3">
    <span>Parent 3</span>
    <ul>
      <li>Children 1</li> 
      <li>Children 2</li>
    </ul>
  </li>
</ul>

You could still style this however you want to give it the appearance you want, although it may not be as easy if you really are displaying tabular data about the parents and children.

With that code, however, you could then simplify the above with a much more efficient:

$('ul > li').each(function() {
    var count = $(this).find('li').length;
    $('span', this).append(' (' + count + ')');
});

If changing the code from a table to a list is not possible/desired, but you have access to the server-side code that presumably generates this table, you could at least make things easier then by giving all the children a class with the ID of the parent, and giving all the parents a common class:

<table>
    <tr id="parent_1" class="parent">
        <td>Parent 1</td>
    </tr>
    <tr class="child parent-1">
        <td>Child 1</td>
    </tr>
    <tr class="child parent-1">
        <td>Child 2</td>
    </tr>
    <tr id="parent_2" class="parent">
        <td>Parent2</td>
    </tr>
    <tr class="child parent-2">
        <td>Child 1</td>
    </tr>
    <tr id="parent_3" class="parent">
        <td>Parent3</td>
    </tr>
    <tr class="child parent-3">
        <td>Child 1</td>
    </tr>
    <tr class="child parent-3">
        <td>Child 2</td>
    </tr>
    <tr class="child parent-3">
        <td>Child 3</td>
    </tr>
</table>

Which would then allow you to do this, much faster than the original solution:

$('tr.parent').each(function() {
    var id = $(this).attr('id').split('_').pop();
    var count = $('tr.parent-' + id).length;
    $(this).find('td').append(' (' + count + ')');
});

Upvotes: 7

Joel
Joel

Reputation: 19368

Because your html doesn't actually place the child nodes below the parent nodes in markup, the easiest way to do this will be to loop through all the TR's and count up class="child" for each parent. Paolo's code should do this for you.

Better would be to have the child nodes defined as actually children of the parent td, then jquery can simplify things for you. If you can afford to refactor your table like this:

<table>
<tr id="parent_1">
<td>Parent 1
<table>
<tr class="child">
<td>Child 1</td>
</tr>
<tr class="child">
<td>Child 2</td>
</tr>
</table>
</td>
</tr>
<tr id="parent_2">
<td>Parent2</td>
</tr>
</table>

then you can write simpler jquery like:

$("td").each(function(){$(this).val($(this).val() + "(" + $(this).find("td").length + ")"); });

Upvotes: 0

Matt
Matt

Reputation: 2230

Give the parents a class of "parent" to make it a bit easier.

$('tr.parent').each(function() {
  var next = $(this).next();
  var count = 1;
  while (next = $(next).next() && $(next).hasClass('child')) {
    count++;
  }
  $(this).find('td').append(' (' + count + ')');
});

Upvotes: 1

Related Questions