How to catch ng-repeat update (angularjs related)

Hi guys, Please let me ask a question. I’ve got a problem that I cannot solve and I’m starting to think it is impossible in Angularjs to have a callback for a finished ng-repeat update. I can successfuly catch the initial rendering by using a directive and the $last property, but this won’t work for view updates e.g. in my case the orderBy filter. The list is quite big and I want to show a spinner when AngularJS is sorting the view, but I cannot catch the moment when I could hide the spinner. There’s no promise like for the $http or a callback option and I’m tearing out my hairs. Experienced users, please help…

As I understand, you want your app to behave like this:

  1. user clicks on a orderBy button or something
  2. spinner should appear
  3. data will be ordered
  4. finished order script
  5. ordered data appears
  6. spinner hides

right?

Exactly. I cannot elegantly detect the point 5 and then call 6 when the 5th point happens. In fact, in the meanwhile, I’ve done this by using a workaround, but a clean solution would be better. My desperate idea is to add a new item to the ngRepeat array just after the orderBy filter was finished, so that I could be able to reuse the $last in the ngRepeatDirective I’ve created for the initial load because in that case the new item becomes $last and directive works. This method works but adds 25% to the time amount required by the rendering. I’m not sure if there’s any other way from what I’ve read on the Internet since yesterday.

So there are no events that get emitted when ng-repeat is done loading data. But what you can do is work with some attributes that come with ng-repeat.

https://docs.angularjs.org/api/ng/directive/ngRepeat

So with that, we can watch for the $last attribute.

.directive('onFinishRender', function ($timeout) {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            if (scope.$last === true) {
                $timeout(function () {
                    scope.$emit('ngRepeatFinished');
                });
            }
        }
    }
});

Then with that we can catch it inside your scope.

  $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) {
    alert('done'); 
  });

Last thing is that we need to add the on-finish-render attribute to the item we are repeating.

Hopefully this helps.

Thanks, but wrote about this solution in my initial question that it doesn’t work. :slight_smile: I have been utilizing the $last solution in the same way it only works at the loading. Only for the initial render. In case of the orderBy or other filters the directive cannot catch the view update because there are no new items in the data array for the ngRepeat and the $last is not changed. I’m looking for something that will work each time the view is updated (e.g. in a case of filtering), but currently only a workaround with adding a dummy item and then removing it allows me to catch the $last change and act somehow to the $last change. However this is not elegant, but I’m afraid (upon long reading and searching for a solution) that there’s no other way. Or maybe you know some?

Hmm, alright. Yeah I’m not sure this will be possible then.