2

I have a list loaded through ng-repeat where each element contains an img tag. I'd like to show some sort of loading indicator (occluding the list items) until every image within every item has finished loading.

I guess I would need to hook into some event broadcast by the angular back-img directive but I don't really know where to start here.

2
  • Check if this answers your problem: stackoverflow.com/questions/16174238/… Commented Mar 10, 2014 at 1:14
  • yeah, back-img is a directive my colleague wrote that I needed to get rid of in order to move forward :) Commented Mar 10, 2014 at 3:56

2 Answers 2

3

Okay, so I solved my problem. First of all, @Vladimir, you're totally right -- back-img was a directive my colleague wrote, which obscured the solution to me for a while.

What I've done is write a really simple directive that calls a $scope-bound function on the img's load event. My controller counts the number of images that have loaded, and once enough images have loaded, it removes the loading indicator and shows the list of images. Here's a summary of the code:

My directive:

app.directive('loadedImage', function($parse) { return { restrict: 'A', scope: true, link: function(scope, element, attrs) { element.bind("load", function(event) { var invoker = $parse(attrs.loadedCallback); invoker(scope); }); } } }); 

Within the element:

<img ng-src='{{ item.large }}' loaded-image loaded-callback="imageLoaded(r.id)"> 

And finally, within the controller:

$scope.numLoaded = 0; $scope.showLoading = true; $scope.showImages = false; $scope.imageLoaded = function(id) { $scope.numLoaded++; if ($scope.numLoaded > 9) { $scope.showLoading = false; $timeout(function() { $scope.showImages = true; }, 500) //show images once loading indicator has faded away }; }; 

I'm not sure this is the right approach, but it reliably works for me!

Sign up to request clarification or add additional context in comments.

4 Comments

I believe you were referring to me, not Kyo. If you liked my answer of adding an event listener on load and counting the loads to determine when youre done, please mark my answer as such
P.S. dont forget to unbind the event once it triggers
Unless its by design you dont need to do a half-a-second timeout. If youre not seeing instant changes its because youre not running your function invocation inside the scope digest cycle. In other words you need to do scope.apply(function(){ $parse(attrs.loadedCallback) (scope);}); inside onload function
@VladimirGurovich the 500 ms timer allows a loading screen to fade away completely before the images fade in, and I'll totally rewrite that callback to run in the $digest cycle. Thank you for all the help!
1

I am not aware of any back-img directive, but image loading is asynchronous and you cant generally guarantee that your 3rd image will load before your 8th image.

WHat I would do is add an 'onload' listener to every img tag that gets added by ng-repeat and simply figure out when all of your images have loaded by keeping count of 'onload' hits and comparing it against the total number of images.

This is essentially what https://github.com/desandro/imagesloaded does, but in the jquery-land.

2 Comments

Yeah, I basically did that, but in the angular way (I think)
Yep, i didnt say you should use that jquery plugin(in fact I wouldnt recommend using this particular plugin with angular), i simply listed it as a reference

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.