Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS: Remove $watch from ng-repeat

I've built a report which uses a set of nested ng-repeat directives to create what can be an enormous table. It works well to build the table, but after that, the scrolling performance is affected greatly - I assume this is due to what must be the large number of watches created by the ng-repeats.

The report only has to be built once and then is static. I don't need to watch the data continually.

I have two questions:

A) is there anyway to see a list of all the variables Angular is currently watching?

EDIT: This post was a great help in learning how to benchmark

B) Is there anyway to tell Angular to stop all of the watches it is doing? I've seen lots of posts about canceling watches which one sets up oneself, but that these are native directives, I'm not sure how I'd tap into them.

My preference would be to have a variable that I can say "if truthy, then do all watches, if not, then do not watch" or a function to just say "start watches" and "stop watches".

I have set up a very nice DOM watching service which can tell when all of the ng-repeats have executed, so I can know when I want to stop watching.

This is the table itself. Aside from tk-ng-repeat-completed, the other "tk-" attributes are just used for data and aren't actually directives.

<div class="table-responsive">

    <table tk-sticky-column id="records" class="table table-striped table-hover table-condensed">

        <!-- tbody[n] -->
        <tbody class="dataset" ng-repeat="dataset in report.data track by $index" tk-ng-repeat-completed>
            <!-- row[0] -->
            <tr class="headline">
                <!-- header[0] label -->
                <th class="headline" style="background-color:#042E34;">
                    <div style="width:200px;"><h4>{{report.labels.y[$index]}}</h4></div>
                </th>
                <!-- header[n] label -->
                <th ng-repeat="x_label in report.labels.x" tk-ng-repeat-completed
                    class="datapoint date"
                    tk-raw-data="{{x_label}}">
                    <em><small>{{x_label}}</small></em></th>
                <!-- header[last] space for addition @todo remove this, add during calculations -->
                <th class="date"></th>  
            </tr>
            <!-- row[n] -->
            <tr ng-repeat="(key, datapoints) in dataset" tk-metric-key="{{key}}">
                <!-- column[0] label -->
                <td tk-metric-key="{{key}}" 
                    tk-calc="{{report.labels.data[key].calc}}"
                    class="rowdesc begin">{{key}}</td>
                <!-- column[n] data -->
                <td ng-repeat="datapoint in datapoints track by $index" tk-ng-repeat-completed
                    ypos="{{$parent.$parent.$parent.$index}}" xpos="{{$index}}" tk-metric-key="{{key}}"
                    class="datapoint"
                    tk-raw-data="{{datapoint}}">
                        {{datapoint}}</td>
            </tr>

        </tbody>

    </table>

</div>
like image 500
dmgig Avatar asked Aug 12 '15 20:08

dmgig


People also ask

What can I use instead of NG-repeat?

But ng-repeat is not the right thing to use when you have large datasets as it involves heavy DOM manipulations. And you should consider using ng-repeat with pagination. You can consider using transclusion inside a custom directive, to achieve the behavior you are looking for without using ng-repeat.

Where is the last element in NG-repeat?

$first and $last It's common when using ng-repeat to add specific behavior to the first or last element of the loop, e.g. special styling around the edges. Instead, ng-repeat already supplies you with two ready boolean properties. $first is true for the first element, and $last is true for the last element.

Does ng-repeat create a new scope?

Each iteration of ng-repeat creates a new child scope, and that new child scope always gets a new property.

What is Ng-repeat in AngularJS?

AngularJS ng-repeat Directive The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.


1 Answers

I'd recommend checking out the single-bind syntax they introduced in 1.3, if you're on a version greater than or equal to that one. It works really well and is very simple to implement. Here's an example:

normal syntax, which creates a watcher for each variable:

<div ng-repeat="foo in vm.bar">
  {{foo}}
</div>

single-bind syntax, with no watcher on the nested variable inside the repeat:

<div ng-repeat="foo in vm.bar">
  {{::foo}}
</div>

edit:

I forgot to mention that if your data isn't going to change at all after it gets populated the first time (e.g. from a $http.get), you can also just use the single-bind syntax on the top level ng-repeat:

<div ng-repeat="foo in ::vm.bar">
  {{::foo}}
</div>
like image 98
wesww Avatar answered Sep 21 '22 19:09

wesww