Akash Agrawal
Akash Agrawal

Reputation: 2299

ng-repeat takes too much time to render data

I know there are many questions already posted for the same issue but none of the solutions work in my case.

On calling a web service I get JSON response. In this JSON, there are around 2000+ objects from which I need to display data on the table. I want to display all (2000+) records in the table and Yes, I cannot limit or paginate, need to display it on a single page (I know it's stupid but it's the business requirement). I don't need sorting or searching.

Data transfer is about 2MB and the request completes in about 2-4 secs approx. but it takes around 10-15 secs to data render on the page.

Now, what I am looking for is either speed ng-repeat binding things up (if possible) or display the data as soon as I receive it and keep on adding it until all rows are displayed.

Check out the code below :

HTML

<table class="table table-bordered table-striped cf">
<thead style="color: #333;">
<tr>
<td>Asset Name</td>
<td>Date/ Time</td>
<td>Location</td>
<td>Ignition</td>
<td>Speed</td>
<td>Heading</td>
<td>Direction</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="cols in tableData">
<td>{{ cols.aN }}</td>
<td>{{ cols.dT }}</td>
<td>{{ cols.Lat }}, {{ cols.Lon }}</td>
<td>{{ cols.I }}</td>
<td>{{ cols.S }}</td>
<td>{{ cols.H }}</td>
<td>{{ cols.D }}</td>
</tr>
</tbody>
</table>

JS

var ignition_text = '';
var lat = '';
var lon = '';
for (var i = 0; i < data.length; i++) {
    if (data[i].ignition = 1) {
        ignition_text = "On";
    } else {
        ignition_text = "Off";
    }
    $scope.$apply(function() {
        $scope.tableData.push({
            aN: name,
            dT: data[i].eventUTCTime,
            Lat: data[i].latitudeDegrees,
            Lon: data[i].longitudeDegrees,
            I: ignition_text,
            S: data[i].speedMPH,
            H: data[i].longitudeDegrees,
            D: data[i].latitudeDegrees
        });
    });
}

Thanks in advance!

Upvotes: 1

Views: 1163

Answers (2)

Ronald91
Ronald91

Reputation: 1776

Here is a plunk that has a similar data size but loads much faster http://plnkr.co/edit/I4rN1ZMaR3e1mbcsJ9Ka. If you were to make a quick plunk I could use your data and edit your code but from the looks you just need the main assignment to the scope without the apply for the data and add a track by to the ng-repeat. SN: You would want to manipulate your data inside the for loop then do the assignment to the scope.

for (var i = 0; i < data.length; i++) {
    if (data[i].ignition = 1) {
        ignition_text = "On";
    } else {
        ignition_text = "Off";
    }
    }
    $scope.tableData=data;

JS

 $http.get("largeData.json").then(function(response) {
    vm.test = response.data;
  });

HTML

<tbody>
      <tr ng-repeat="(key, value) in main.test track by $index ">
        <td>{{ value.ask }}</td>
        <td>{{ value.bid }}</td>
        <td>{{ value.volume_btc }}, {{ value.volume_percent }}</td>
        <td>{{ value.last }}</td>
        <td>{{ value.timestamp }}</td>
      </tr>
    </tbody>

Upvotes: 2

PerfectPixel
PerfectPixel

Reputation: 1968

You probably wont need $scope.$apply at all. And even if you need it, you should only use it once you pushed all data to the table. Otherwise, every added entry will force an digest-cycle. Just build your array and assign the finished array to the scope-variable. Then angular will only build the table once.

Depending on the nature of your variable name you may be able to eliminate the array building as well and just use the data you are downloading. Apart from nameyou just use that data anyway.

Upvotes: 2

Related Questions