4

I have a problem of getting a ngRepeat table's height when page loaded

I'm trying to get the height when event $viewContentLoaded fires, but the table's height equals the height of the title bar of the table. My table looks like this:

http://media-cache-ak0.pinimg.com/originals/d9/cc/70/d9cc70b55e750d92f17685e8c57692b7.jpg

How to get the correct height of the table? Thanks a lot.

Here is my code:

$scope.$on('$viewContentLoaded', function(){
    var elem = angular.element(document.getElementById('ng-repeat-table-test'));
    console.log(elem.height());
});

The actual table height measured by Chrome Developer tool is 234px. However, the above code print out 100px, which is the height of the title bar.

More Code:

code for rendering the table:

 <table id="ng-repeat-table-test">
     <tr id="title">
         <td>Car Types</td>
     </tr>
     <tr class="row" ng-repeat="car in cars">
         <td>{{car.name}}</td>
     </tr>
  </table>

CSS:

table{
    margin-left: auto;
    margin-right: auto;
    margin-top: 10px;
}
tr#title{
    height: 100px;
    background-color: #ccc;
}
tr.row{
    padding-top: 10px;
    border-top: 1px solid #ccc;
}
tr.row:first-child{
    border-top: none;
}
tr.row td{
    padding-top: 10px;
    height: 56px;
    vertical-align: top;
}

Small chunk of code on jsfiddle

Community
  • 1
  • 1
Peng
  • 434
  • 5
  • 14

1 Answers1

2

$viewContentLoaded is fired when Angular finishes the compilation, that doesn't mean the browser has rendered the DOM.

So in your case, the problem is that when $viewContentLoaded's callback is executed the table has no rows painted yet, that's why you are getting the wrong height.

Try delaying (move to the end of the queue) the execution of that with $timeout, so the DOM can be manipulated before you get the element's height.

$scope.$on('$viewContentLoaded', function(){
  $timeout(function () {
     var elem = angular.element(document.getElementById('ng-repeat-table-test'));
     console.log(elem.height());
  });
});
Bertrand
  • 13,540
  • 5
  • 39
  • 48
  • Thanks for the help. The code works well! Just be curious, is the $timeout the only solution for this? Is there possible to find a event fire after DOM finish rendering? – Peng Aug 27 '14 at 15:18
  • I could think in other workarounds but $timeout is probably the best. At the moment it is impossible to know when rendering is finished because [DOM has no such event](http://en.wikipedia.org/wiki/DOM_events#HTML_events). – Bertrand Aug 27 '14 at 15:42
  • I see. I'm surprised that there's no such event exists out there. I mean such event can be very useful in certain situation. I got another concern about the $timeout. If the table has a huge dataset and ngRepeat takes a long time to be populated, the $timeout might not be able to take care of this situation. Is that correct? – Peng Aug 27 '14 at 15:57
  • 1
    No need to worry about that, Javascript and DOM rendering are serial (same thread), so when we re-schedule the execution with timeout, we are putting that piece of code at the end of the queue and this would guarantee that the rendering finishes before. Have a look at [this question](http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful) – Bertrand Aug 27 '14 at 16:31
  • 1
    Great. It's good to know $timeout can rearrange the execution at the end of the queue. Thank you so so much for the help. I have learned a lot from you today. – Peng Aug 27 '14 at 16:44
  • in my solution $timeout not working, showing $timeout is not a function – Sathishkumar Jan 31 '20 at 11:06