Is there a way to speed up my grid when I have many rows?

I have code that creates a grid as follows:

<div ng-repeat="row in home.grid.data track by row.examId"> <div>{{ row.examId }}</div> <div>xxxx</div> </div> 

After that I have more columns.

Is there a way to speed up my page? It seems that when I have a lot of data in the grid, then the pages respond slowly. Will it matter if I used the ng model in the input type field for row.examId. Note that some of the following fields can be edited, but most of them are just displayed only.

+6
source share
3 answers

I believe bindonce does exactly what you need.

By reducing the number of observers, it allows the page to become more responsive. Check out their demos .

+4
source

Here is what I did. There are two ways. Regardless of both solutions, use bindOnce . Keep track of the number of watchers on the page. Look at the end of this decision - how to track observers on a page.

I added solution 3 and it works amazingly, the style is a bit more complicated

Solution 1:

Use the pagination control with an anchor once.

Solution 2 This is what worked for me, and it is very elegant. You repeat bindOnce and then implement endless scrolling. I followed this blog post and it works like a charm. The idea is that you limit the number of lines and change the limit when scrolling.

 ng-repeat="item in items | orderBy:prop | filter:query | limitTo:limit" 

Essentially, your html will look like this. I changed the OP code to use bindonce.

  <div id="estates-listing" extend-height> <div class="content" infinite-scroll="addMoreItems()" infinite-scroll-distance="2"> <div class="content-wrapper"> <div class="house" bindonce="estate" ng-animate="'animate'" ng-class="{inactive: (selectedEstate != null || selectedEstate != undefined) && estate.id!=selectedEstate.id , active:(selectedEstate != null || selectedEstate != undefined) && estate.id==selectedEstate.id}" ng-repeat="estate in estates | orderBy: orderProp : orderReverse | limitTo: config.itemsDisplayedInList track by estate.id" ng-mouseover="highlightMarker(estate)" ng-mouseleave="leaveMarker(estate)" ng-click="showDetailview(estate.id)" > <div id="l-el{{estate.id}}"> </div> </div> </div> </div> </div> 

Here is the endless scroll directive from the message. Add this to your application, please do not use standard infinite scrolling with bower setting.

 app.directive('infiniteScroll', [ '$rootScope', '$window', '$timeout', function($rootScope, $window, $timeout) { return { link: function(scope, elem, attrs) { var checkWhenEnabled, handler, scrollDistance, scrollEnabled; $window = angular.element($window); elem.css('overflow-y', 'scroll'); elem.css('overflow-x', 'hidden'); elem.css('height', 'inherit'); scrollDistance = 0; if (attrs.infiniteScrollDistance != null) { scope.$watch(attrs.infiniteScrollDistance, function(value) { return scrollDistance = parseInt(value, 10); }); } scrollEnabled = true; checkWhenEnabled = false; if (attrs.infiniteScrollDisabled != null) { scope.$watch(attrs.infiniteScrollDisabled, function(value) { scrollEnabled = !value; if (scrollEnabled && checkWhenEnabled) { checkWhenEnabled = false; return handler(); } }); } $rootScope.$on('refreshStart', function(event, parameters){ elem.animate({ scrollTop: "0" }); }); handler = function() { var container, elementBottom, remaining, shouldScroll, containerBottom; container = $(elem.children()[0]); elementBottom = elem.offset().top + elem.height(); containerBottom = container.offset().top + container.height(); remaining = containerBottom - elementBottom ; shouldScroll = remaining <= elem.height() * scrollDistance; if (shouldScroll && scrollEnabled) { if ($rootScope.$$phase) { return scope.$eval(attrs.infiniteScroll); } else { return scope.$apply(attrs.infiniteScroll); } } else if (shouldScroll) { return checkWhenEnabled = true; } }; elem.on('scroll', handler); scope.$on('$destroy', function() { return $window.off('scroll', handler); }); return $timeout((function() { if (attrs.infiniteScrollImmediateCheck) { if (scope.$eval(attrs.infiniteScrollImmediateCheck)) { return handler(); } } else { return handler(); } }), 0); } }; } ]); 

Solution 3: Be adventurous and use UI-Grid , UI Grid is a new ng-grid. This is not production ready, but we play in production in a table where we have more than 1000 entries - out of the box it is amazing. The tutorials are extensive, but do not support SO. It has built-in virtualization and, since it is an extension of ng-grid, has a lot of backward compatibility. Here is an example with 10,000 lines

The number of observers per page: Here is the function of tracking the number of observers per page. The rule of the thumb never exceeds 2500 observers, but we are limited to 1000.

  $scope.TotalWatchers = function () { var root = $(document.getElementsByTagName('body')); var watchers = 0; var f = function (element) { if (element.data().hasOwnProperty('$scope')) { watchers += (element.data().$scope.$$watchers || []).length; } angular.forEach(element.children(), function (childElement) { f(angular.element(childElement)); }); }; f(root); return watchers; }; 
+4
source

The most important thing I found to help with large tables was to limit the event binding to the parent and use the bubbles to capture the events of the children.

In the case of a parent, you can get which target was deleted. I am using the following code.

 obj.onclick = function (e) { e = window.event || e; var t = e.target || e.srcElement; } 

in this case, e is your regular event object, and t is the object that was the original target before the event bloated. You need to use t because 'this' refers to an object to which the event is not bound to the object that raised the event.

Where I used code that was a really big table, it reduced the table's rendering time by almost 80% by moving events to the parent node, which was static. It also helps if you need to update the content since you do not need to relink any events.

Hope this helps.

+1
source

Source: https://habr.com/ru/post/975025/


All Articles