Sameera Thilakasiri
Sameera Thilakasiri

Reputation: 9508

AngularJS check image for 404 and get dynamic URL for image src

This is my repeater:

<div ng-click="selected(entity)" ng-if="entity.is_organization == true">
    <div class="row">
        <div class="cell info">
            <span class="text" ng-bind-html="entity.label"></span>
        </div>
        <div class="cell img" ng-show="isImageAvailable">
            <img class="image" ng-src="checkImageAvailable(entity.thumbnail[0])">
        </div>
    </div>
</div>

checkImageAvailable in the controller:

$scope.isImageAvailable = false;
$scope.checkImageAvailable = function(image_url){
  var img = new Image();
  img.onload = function (){
    $scope.isImageAvailable = true;
  };
  img.onerror = function (){
    $scope.isImageAvailable = false;
  };
  img.src = image_url;
  if($scope.isImageAvailable){
     return image_url;
  }
};

I get the entity.thumbnail[0] from the JSON, but even it has a URL it doesnt exist. So I do check it using checkImageAvailable. If image is not available, set isImageAvailable set to false, so image parent container ng-show is taken care to hide the image placeholder from browser. Same time on the console log it shows: http://localhost/checkImageAvailable(entity.thumbnail[0]) is 404

What may be the mistake I'm doing in front of AngularJS.

Upvotes: 0

Views: 1603

Answers (1)

sirrocco
sirrocco

Reputation: 8055

One thing that's wrong is that by the time you set:

$scope.isImageAvailable = true; //or false

you're outside the angular lifecycle - so you have to call $scope.$apply();

Any time you make changes to the angular scope outside of an angular event, you have to call $apply().

Checking isImageAvailable will probably be false as onerror/onload will be called back asynchronously so you could just return image_url right away.

Edit

So it turns out that you would have to call the method like:

ng-src="{{checkImageAvailable(entity.thumbnail[0])}}"

But there's a problem because angular keeps calling the method in a loop. Even if you do:

ng-src="{{::checkImageAvailable(entity.thumbnail[0])}}"

it still gets called 3 times. I don't know why 3.

So at this point I would try with a different approach: custom directive. When it initializes you set the image as hidden, attach the onload/onerror handlers to the element and then depending on which gets called, you show the image or not.

Let me know if it doesn't make sense. Demo: http://jsbin.com/yenipodimi/1/edit?html,js,output

Upvotes: 2

Related Questions