In angularjs 1.2 operations like filtering an ng-repeat
with many rows (>2,000 rows) can become quite slow (>1 sec).
I know I can optimize execution times using limitTo
, pagination, custom filters, etc. but I'm still interested to know if it's possible to show a loading animation while the browser is busy running long scripts.
In case of angular I think that could be invoked whenever $digest
is running because that seems to be the main function that takes up most time and might be called several times.
In a related question there were no useful answers given. Any help greatly appreciated!
The problem is that as long as Javascript is executing, the UI gets no chance to update. Even if you present a spinner before filtering, it will appear "frozen" as long as Angular is busy.
A way to overcome this is to filter in chunks and, if more data are available, filter again after a small $timeout
. The timeout gives the UI thread a chance to run and display changes and animations.
A fiddle demonstrating the principle is here.
It does not use Angular's filters (they are synchronous). Instead it filters the data
array with the following function:
function filter() { var i=0, filtered = []; innerFilter(); function innerFilter() { var counter; for( counter=0; i < $scope.data.length && counter < 5; counter++, i++ ) { ///////////////////////////////////////////////////////// // REAL FILTER LOGIC; BETTER SPLIT TO ANOTHER FUNCTION // if( $scope.data[i].indexOf($scope.filter) >= 0 ) { filtered.push($scope.data[i]); } ///////////////////////////////////////////////////////// } if( i === $scope.data.length ) { $scope.filteredData = filtered; $scope.filtering = false; } else { $timeout(innerFilter, 10); } } }
It requires 2 support variables: $scope.filtering
is true
when the filter is active, giving us the chance to display the spinner and disable the input; $scope.filteredData
receives the result of the filter.
There are 3 hidden parameters:
counter < 5
) is small on purpose to demonstrate the effect$timeout(innerFilter, 10)
) should be small, but enough to give the UI thread some time to be responsiveThis is only a proof of concept; I would suggest refactoring it (to a directive probably) for real use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With