108

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?

1
  • 1
    Take a look at $http Response Interceptors. You could use this to register a callback when the promise resolves Commented Jul 26, 2013 at 14:53

6 Answers 6

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 />
Sign up to request clarification or add additional context in comments.

2 Comments

what about a failure callback?
What about progressive image?
151

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

4 Comments

That's correct. Mikach's solution didn't work for me until I used $apply() as you did.
This is the best of the answers provided. Totally eliminates the need for any JQUERY loading as well.
Thank you for putting semi-colons so lint wouldn't explode.
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');
        });
    }
  };
});

1 Comment

Might be better to have that in an 'imageonerror' directive so you can perform a different action.
5

My answer:

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

Comments

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);
                });
            }
        };
    })

Comments

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);
            });
        }
    };

}]);

2 Comments

what you mean by "$apply() should only be used by external sources"? i'm not following.
@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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.