Angular\'s ng-src keeps previous model until it preloads image internally. I am using different image for the banner on each page, when I switch routes, i change main view,
Instead of using
element.on('load', function() {});
use imagesLoaded plugin. It will speed up dramatically your images.
So the final code would be:
link: function(scope, element) {
imagesLoaded(element, function() {
});
scope.$watch('ngSrc', function() {
});
}
If you want you can pass the image fail and image loader as attributes for the directive....
myApp.directive("mySrc", function() {
return {
link: function(scope, element, attrs) {
var img, loadImage;
var IMAGE_LOAD="123.jpg";
var IMAGE_FAIL="123.jpg";
img = null;
loadImage = function() {
element[0].src = IMAGE_LOAD;
img = new Image();
img.src = attrs.mySrc;
img.onload = function() {
element[0].src = attrs.mySrc;
};
img.onerror=function ()
{
element[0].src = IMAGE_FAIL;
}
};
loadImage();
}
};
});
I think this is perhaps the most elegant solution because the directive actually creates the spinner and removes it automatically:
app.directive('spinnerLoad', [function spinnerLoad() {
return {
restrict: 'A',
link: function spinnerLoadLink(scope, elem, attrs) {
scope.$watch('ngSrc', function watchNgSrc() {
elem.hide();
elem.after('<i class="fa fa-spinner fa-lg fa-spin"></i>'); // add spinner
});
elem.on('load', function onLoad() {
elem.show();
elem.next('i.fa-spinner').remove(); // remove spinner
});
}
};
}]);
Here is the html:
<img ng-src='{{imgUrl}}' spinner-load />
Note: you'll need to be using font-awesome for this to work as described here