107

I have images looking like <img ng-src="dynamically inserted url"/>. When a single image is loaded, I need to apply iScroll refresh() method so that to make image scrollable.

What is the best way to know when an image is fully loaded to run some callback?

Sergei Basharov
  • 51,276
  • 73
  • 200
  • 335
  • 1
    Take a look at [$http Response Interceptors](http://docs.angularjs.org/api/ng.$http). You could use this to register a callback when the promise resolves – Mark Meyer Jul 26 '13 at 14:53

6 Answers6

188

Here is an example how to call image onload http://jsfiddle.net/2CsfZ/2/

Basic idea is create a directive and add it as attribute to img tag.

JS:

app.directive('imageonload', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('load', function() {
                alert('image is loaded');
            });
            element.bind('error', function(){
                alert('image could not be loaded');
            });
        }
    };
});

HTML:

 <img ng-src="{{src}}" imageonload />
chris Frisina
  • 19,086
  • 22
  • 87
  • 167
mikach
  • 2,427
  • 2
  • 14
  • 15
150

I modified this a little so that custom $scope methods can be called:

<img ng-src="{{src}}" imageonload="doThis()" />

The directive:

.directive('imageonload', function() {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                element.bind('load', function() {
                    //call the function that was passed
                    scope.$apply(attrs.imageonload);
                });
            }
        };
    })

Hope someone finds it VERY useful. Thanks @mikach

The doThis() function would then be a $scope method

Peter
  • 6,509
  • 4
  • 30
  • 34
9

@ Oleg Tikhonov: Just updated the previous code.. @ mikach Thanks..)

app.directive('imageonload', function() {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
        element.bind('load', function() {
            alert('image is loaded');
        });
        element.bind('error', function(){
             alert('image could not be loaded');
        });
    }
  };
});
Aurelio
  • 24,702
  • 9
  • 60
  • 63
Kailash
  • 123
  • 1
  • 7
5

My answer:

 var img = new Image();
 var imgUrl = "path_to_image.jpg";
 img.src = imgUrl;
 img.onload = function () {
      $scope.pic = img.src;
 }
4

Just updated the previous code..

<img ng-src="{{urlImg}}" imageonload="myOnLoadImagenFunction">

and directive...

    .directive('imageonload', function() {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                element.bind('load', function() {
                    scope.$apply(attrs.imageonload)(true);
                });
                element.bind('error', function(){
                  scope.$apply(attrs.imageonload)(false);
                });
            }
        };
    })
0

Basically this is the solution I ended up using.

$apply() should only be used by external sources in the right circumstances.

rather then using apply, I've thrown the scope updating to end of the call stack. Works as good as "scope.$apply(attrs.imageonload)(true);".

window.app.directive("onImageload", ["$timeout", function($timeout) {

    function timeOut(value, scope) {
        $timeout(function() {
            scope.imageLoaded = value;
        });
    }

    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('load', function() {
                timeOut(true, scope);
            }).bind('error', function() {
                timeOut(false, scope);
            });
        }
    };

}]);
Doug
  • 76
  • 1
  • 4
  • what you mean by "`$apply()` should only be used by external sources"? i'm not following. – genuinefafa Sep 14 '16 at 13:25
  • @genuinefafa What he means by 'external sources' is non-Angular code. So for instance if you're using a generic JS event listener to call into code that changes $scope, you would need to use $apply there. But if it's an Angular event or a $scope function you don't need $apply because the $digest cycle is already running from Angular methods. – tpartee Aug 10 '17 at 17:57