0

Using angularjs (1.3) with webapi here.

I have UI where the user can upload a excel file. My api reads the excel file and returns rows data back to the UI in JSON.

The UI then reads the JSON and binds it back the UI table.

The rows and columns of this UI table are dynamically generated and are not fixed, because of which I am using contenteditable in HTML as the user can add more rows.

I can read from the the JSON fine and populate the array that holds these json values. The issue is while rendering, the screen is frozen and takes time to render all the data. I am currently binding about 800 rows and the screen freezes and takes about 10-15 seconds or more to fill up the UI table. I would be having lot more data so looking for a solution for this.

I tried to debug and can see that there is no issue getting data back from the API, and reading JSON from the API. There is also no issue while populating the array. Once the array populates thats when the issue comes. The UI freezes and takes time to render this data.

I am not sure whats going on here or why it takes so time to render. Below is some sample relevant code:

//Read json from the API

$http.get('https://api.myjson.com/bins/d1ugw').success(function(data) {
if (data.length > 0) {   

  $scope.setJson = data;
  $scope.initializeTable(true);
  var columns = $scope.targetTable.columns;

  //These are the 3 columns of the Table but can vary dynamically(currently just hardcoding it)
  var refColName = "state, month , year";

  //Push the columns to the table array
  var colArray = refColName.split(',');
  for (var i = 0; i < colArray.length; i++) {
    $scope.targetTable.columns.push({
      id: columns.length,
      refColName: refColName.split(',')[i]
    });
  }

  //Read the values from the json
  var idValues = $scope.getTableValues($scope.setJson, 'id');
  var commentValues = $scope.getTableValues($scope.setJson, 'comment');
  var rowValues = $scope.getTableValues($scope.setJson, 'refcol');
  var setIdValues = $scope.getTableValues($scope.setJson, 'sid');

  //Push the data back to the table array.
  $scope.pushRowData($scope.targetTable, rowValues, commentValues, idValues, setIdValues);
  //Till the above steps everything happens quickly and I can see $scope.targetTable being populated with my json. 
  //But after the above step the screen just freezes and takes time to show the entire data on the UI table.
 }
  });

Below is the relevant code for the UI:

<tbody>
    <tr ng-repeat="r in targetTable.rows">
      <td class="fixed-width">
        <span>
            <a class="btn-xs" ng-show="row == $index" ng-if="targetTable.rows.length > 1"><i class="fa fa-times-circle" aria-hidden="true"></i></a>
        </span>
        <span contenteditable="true" ng-model="r.tableId" ng-change="addNewRow(r.tableId, r)">{{r.tableId}}</span>
      </td>
      <td class="fixed-width" contenteditable="true" ng-repeat="column in targetTable.columns" ng-model="r[column.id]" ng-change="rowDataChange(r[column.id])"></td>
      <td class="comment-fixed-width" contenteditable="true" ng-model="r.comment" ng-change="rowDataChange(r.comment)"></td>
      <td class="blank fixed-width" colspan="2" ng-model="r[column.id]"></td>
    </tr>
  </tbody>

I have created the below JSFiddle to show my example and issue I am facing.

http://jsfiddle.net/aman1981/u1vbeos5/312/

I have also added comments in my jsfiddle for showing what method does what.

Would appreciate if anyone can help my resovling this issue.

2
  • There are numerous table modules around you could use that may improve performance. Also suggest upgrading angular version. Making rows editable on demand would also cut down a significant number of directives that need to be compiled Commented Dec 17, 2018 at 14:09
  • @charlietfl at this moment I cannot upgrade angular as its being used project wide. I have to look at other table solution, any open source versions you can share which are good? Also even if my array populates fast why does the UI takes so long to render. I dont think I have any particular code that makes up for the slowness. Commented Dec 17, 2018 at 14:30

3 Answers 3

1

Here are some performance stats:

with contenteditable (~4000 digest calls) = 1.800ms -> http://prntscr.com/lweugn

without contenteditable (~4 digest calls) = 1.300ms -> http://prntscr.com/lweusn

with pagination just showing the first 50 results = 0.200ms -> http://prntscr.com/lwev09

You loose the most performance because of the DOM changes obviously. But keep in mind that the number and duration of digest cycles is key for good performance. Especially when you have a huge amount of watchers. Here is a Direct comparison: http://prntscr.com/lwf1nn As you can see the digest loop is burning 30% of your performance overall but is not the reason for your frame drop. The frame drop is mostly caused of the DOM changes. Drawing such a big table takes some time.

Further the table starts rendering when your REST call is finished. This call takes in my case roughly additional 1.700ms. So it takes nearly 3.500ms from start until rendered results. Even with pagination 1.900ms.

I would recommend a pagination with search but you can try to increase the performance anyway.

Helpful links would be:

https://stackoverflow.com/a/47347260/8196542

https://www.codeproject.com/Articles/1173869/%2FArticles%2F1173869%2Fng-repeat-performance-degradation-at-case-of-very

Sign up to request clarification or add additional context in comments.

1 Comment

I tried to use your suggestion as posted in your link and use the javascript of smart scroll but its not working. Would you have some time to look into this. Here is my updated jsfiddle: jsfiddle.net/aman1981/mwLbr9o8/12
1

First, I recommend that you upgrade the Angular version to the most advanced of course if possible. Also check the animate version. Beyond that you thought of using an advanced tabular component such as ag-grid ?, I can load 10000 rows without any problem with it. https://www.ag-grid.com/

2 Comments

In near future we are planning but at this moment we cannot upgrade the angular version. Is there any other solution to this? What other third party grids can integrate with angular js 1.3
You can use ag-grid with angular 1.3 just make sure to take suitable version of it.
0

Your code is triggering the $digest loop over and over. The "watch" method counts how often the $digest cycle is actually called:

var nbDigest = 0;

$scope.$watch(function() {
  nbDigest++;
  console.log(nbDigest);
});

I bet this is the cause of your performance issues.

8 Comments

Okay, and what is the solution?
@Christian if you debug my above code in Jsfiddle the last line does executed very fast and as I mentioned I can see the array populated fast but its just after that screen freezes. Do you see any issue or have any solution here?
I'm not sure it this is the solution for this specific problem. But i had a lot of trouble with the digest Cycle. In your case the digest is called >4000 times. Every Digest means that angular will be forced to check every element which could be different between Model and View and update if so. I would try to save the incoming data first in a buffer and just update with a debounce. I'll try to set up a fiddle
I wanted to set up an fiddle but than i found out that the digests are not called by your model they are called from your contenteditable directive. You could try for debug purpose to don't use them and check if this increase the performance
If I dont use content editable my data doesnt shows up. I tried removing contenteditable but I cant see any data on UI now.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.