Inder
Inder

Reputation: 170

Improve performance of ng-repeat with 1600 items. Causing page load delay and performance issues

I have a UI layout with perfect-scrollbar to render a list of items. There are 1600 items which I need to display (without limiting the number of items displayed with any pagination) within the scrollable section so that user can scroll all the items at once (this is a requirement for me and I have less control over this).

The angular template rendering this view is below:

<my-scrollable-section>
    <div 
        ng-class="myCtrl.itemId == item.itemId ? 'item-active-background' : ''"
        ng-click="myCtrl.itemClickHandler(item)"
        ng-repeat="item in myCtrl.items | filter:myCtrl.search track by item.itemId">
            <span>{{item.name}}</span>
            <div ng-repeat="(key, value) in ::item.models">
                <span>{{::value}}</span>
            </div>
            <div ng-repeat="(key, value) in ::item.frameworks">
                <span>{{::value}}</span>
            </div>
    </div>
</my-scrollable-section>

The filter in this repeat is linked to a search bar just above this view to narrow down the items being displayed.

The problem now is:

  1. The page does not load instantaneously and freezes for 5-8 seconds. The number of watchers is not the cause for this, as I tried one-time bindings to bring the watcher count below 1500.
  2. Once the page has loaded, the scroll is very slow and does not seem user-friendly at all.
  3. I tried suggesting a pagination to limit the number of items being rendered at a time, but as mentioned earlier, I have little control over the requirements and it's required that all items be present on the scrollable list.

Can these load and performance issues be fixed with angular? Please do not suggest infinite-scroll as even if we use an infinite scroll, in the end, once all items are on the page, the UI will again become slow.

Upvotes: 1

Views: 2011

Answers (2)

Omprakash Sharma
Omprakash Sharma

Reputation: 429

// Try with, on scroll call function & update renderLimit value.

check example here - plunker demo

// set initial limit to say 30.
$scope.renderLimit = 30;
// bind this function with directive.
$scope.updateLimit = function(value){
  if(value == 'bottom'){
    $scope.contValue += 1;
    $scope.renderLimit += 30;
  }
};

// directive will be
// custome directive for scrollHandler
app.directive('scrollHandler', function(){
  return{
      scope: { 
             scrollHandler: '&',
             dataChange:'='
         },
      link:function(scope,element){

          scope.$watch(function(){return scope.dataChange;},function(){
              if(element[0].scrollTop > (element[0].scrollHeight - element[0].clientHeight - 50))
                element[0].scrollTop=(element[0].scrollHeight - element[0].clientHeight - 50);
          });
          element.bind('scroll',function(){
              var scrPosition = element[0].scrollTop;

              if(scrPosition === 0)
                 scrPosition = "top";
              else if(scrPosition === (element[0].scrollHeight - element[0].clientHeight))
                 scrPosition = "bottom";
              scope.$apply(function() {
                 scope.scrollHandler()(scrPosition);
               });
          });

      },
      restrict:"A"
  };
});

HTML::

<div scroll-handler="myCtrl.updateLimit" data-change="contValue">
    <div 
            ng-class="myCtrl.itemId == item.itemId ? 'item-active-background' : ''"
            ng-click="myCtrl.itemClickHandler(item)"
            ng-repeat="item in myCtrl.items| limitTo:renderLimit | filter:myCtrl.search track by item.itemId">
      // item contents...
    </div>
</div>

Upvotes: 2

Yaje
Yaje

Reputation: 2831

Have you looked into vs-repeat?

I've been using this api to handle large number of items to be repeated. And i haven't encountered any problems.

Just a simple:

<div vs-repeat> <div ng-repeat="item in someArray"> <!-- content --> </div> </div>

would solve your problem.

Upvotes: 0

Related Questions