Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IE11 slow / freeze with AngularJS's ng-repeat rendering

Currently I have a very sublte problem to solve with IE11 and AngularJS.

My page consists of two nested ng-repeat to create a tabset with a table inside any tab.

Here the code: http://pastebin.com/0fffPz5Z

In the code, each application's object have around 1.000 item's related objects. With a Chrome, Safari and Mozilla I have no problem, all is superfast! With IE11 the page go slow and IE11 show me the message of a too slow page's script....

I've created an IE11 interface's profiling with this result: https://www.dropbox.com/s/y5xuystxht6gjkr/IE11-interface-profiling.png?dl=0

Is this another IE11's bug??? Sorry for my English and thanks in advance for any suggestion.

Edit: Currently (for "debug" purpose) I removed all td's content... the IE11 is still too slow. :(

                <tabset ng-show="!applicationsLoading">
                <tab ng-repeat="application in applications track by application.name">
                    <tab-heading>
                        <em class="fa fa-clock-o fa-fw"></em> {{ application.name }}
                    </tab-heading>
                    <div>
                        <!-- START table responsive-->
                        <div class="table-responsive">
                            <table class="table table-bordered table-hover table-striped">
                                <thead>
                                <tr>
                                    <th></th>
                                    <th></th>
                                    <th></th>
                                    <th></th>
                                    <th></th>
                                    <th></th>
                                    <th></th>
                                </tr>
                                </thead>
                                <tbody>
                                <tr ng-repeat="item in application.items track by item.itemid">
                                    <td></td>
                                    <td></td>
                                    <td>
                                    </td>
                                    <td></td>
                                    <td></td>
                                    <td>
                                    </td>
                                    <!-- Graph or History column -->
                                    <td>
                                    </td>
                                </tr>
                                </tbody>
                            </table>
                        </div>
                        <!-- END table responsive-->
                    </div>
                </tab>
            </tabset>
like image 414
Fabrizio A Avatar asked May 25 '15 18:05

Fabrizio A


People also ask

Is your angular app slow?

Is your app slow? Learn what to watch out when debugging poor performance in your Angular apps! Angular is, by default, a fast and performant framework. While it leaves ample space for improvement by opting out some of its magic, we almost never have to do anything special to write extremely performant code for the average app.

How to improve performance with angular-vs-repeat?

Using this project: angular-vs-repeat will boost up your performance. With this, the browser will render (thus angular will do its dirty-checking) to only so many elements that fit in the scrollable container where you render the elements. Demo here

How do I reduce the number of iterations in AngularJS?

Use break and continue to reduce the number of iterations Maintain the shape of your objects. Learn more about how Angular is so fast watching this video from Misko Hevery Opt-out of the framework’s magic: make sure you use ChangeDetection.OnPush and TrackBy for arrays

How to reduce the Digest frequency in angular?

As the answer of alecxe above, use one-time bounding, if that not proper for you, you can slow the digest frequency with such ng-model-options=" { debounce: 200 } angular option settings And last, you have to use some performance analyser tools to track the bottleneck of the application, and fix them.


2 Answers

AngularJs has limits for rendering bindings per page (In some articles you can find that it is around 2000 bindings). Currently you've just faced this situation. The reason why chrome and Mozilla work smoothly is that DOM operations for them are optimized better. In order to improve your performance try to:

  • avoid using sort in ng-repeat (sort it before insertions)
  • Use one-time bindings (:: syntax)
  • Remove unnecessary watches
  • Optimize digest cycles
  • Use pagination
  • Replace angularjs ng-repeat with ReactJs components (in case of really big amount of data)
like image 177
nesteant Avatar answered Oct 04 '22 13:10

nesteant


Just ran into this same problem. Had everything working perfectly on Chrome, then tested in IE and it kept crashing with anything over 1000 records.

I ended up following this link to add a "lazy load" or "infinite scroll" to my table. So on table load it still pulls all 1000+ records, but instead of loading this data directly into the table, I load it into a big array, then just subset my table of say 50 records. Then create a directive that listens to the scroll on the table, and when it's near the bottom then fire off a function which just adds the next 50 records from the big array into my table array. Here's a direct link to the fiddle from the link above.

HTML

<tbody when-scroll-ends="loadMoreRecords()">
    <tr ng-repeat="row in tableData">
        <td>{{row.attribute}}</td>
    </tr>
</tbody>

Module

angular.module(myApp, []).directive('whenScrollEnds', function () {
    return {
        restrict: "A",
        link: function (scope, element, attrs) {
            var processingScroll = false;

            var visibleHeight = element.height();
            var threshold = 200;

            element.scroll(function () {
                var scrollableHeight = element.prop('scrollHeight');
                var hiddenContentHeight = scrollableHeight - visibleHeight;

                if (hiddenContentHeight - element.scrollTop() <= threshold) {
                    // Scroll is almost at the bottom. Loading more rows
                    scope.$apply(attrs.whenScrollEnds);
                }
            });
        }
    };
});

Controller

function loadTableData() {
    LoadDataService().getData().then(function(response) {
        fullTableList = response.data;
        $scope.tableData = fullTableList.slice(0,50);
    });
}

function loadMoreRecords() {
    // if there's still more than 20 records left, add the next chunk of 20
    if (fullTableList.length - $scope.tableData.length > 20) {
        $scope.tableData = $scope.tableData.concat(fullTableList.slice($scope.tableData.length,$scope.tableData.length + 20));
    } else {
        while ($scope.tableData.length < fullTableList.length) {
            $scope.tableData.push(fullTableList[$scope.tableData.length]);
        }
    }
}
like image 21
amallard Avatar answered Oct 04 '22 12:10

amallard