Join the Stack Overflow Community
Stack Overflow is a community of 6.6 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

My AngulaJS driven frontend gets the data from a local JSON file and will later switch to an API. The data is a list of Project objects with nested lists of Image objects. I'm displaying this data in a loop:

<div id="projects" ng-app="portfolio">
    <div id="projectsList" ng-controller="ProjectsListController as projectsList">
        <div class="projectItem" ng-repeat="projectItem in projectsList.projectsListData._embedded.projects">
            <div class="project-image">
                <img
                    ng-src="{{projectItem._embedded.images[0].src}}"
                    title="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
                    alt="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
                />
            </div>
        </div>
    </div>
</div>

But sometimes the image src is invalid (error 404). It would be better to skip such projects, where the first image (images[0]) cannot be found. How to make the script skip the irrelevant objects?


EDIT

I've already got three answers, but the solutions don't work and I want to explain the problem exactly:

The src property of the images is alwys set. It's not the problem. That means, that checking if it's set or not (like ng-show="projectItem._embedded.images[0].src != ''" or ng-if="{{projectItem._embedded.images[0].src}}") will not work -- cannot work.

It doesn't work -- the src property is set. It's wrong (will cuase the 404 error), but it's set and projectItem._embedded.images[0].src != '' will return true for the "irrelevant" objects as well.

enter image description here

enter image description here

share|improve this question
    
I've come up with an approach for this. Check if its useful for you. Demo : jsbin.com/kedirofako/1/edit?html,js,output – mohamedrias Apr 4 '15 at 11:51
up vote 2 down vote accepted

This is a hacky way of making this work:

To avoid loading images when they throw 404 error or when the images are invalid,

This must be inside your controller. This function checks whether the image URL is valid/invalid.

$scope.imageExists = function(image, object, index) {
    var img = new Image();
    img.onload = function() {
      object[index] = true;
      $scope.$apply();
    }; 
    img.onerror = function() {
      return false;
    };
    img.src = image;
 };

Now in View:

I'm initiating an object called img={}; in the ng-repeat.

Then initializing the value for that index in ng-repeat to $scope.imageExists function. Inside that function, on success of that image load, am setting img[index]= true.

<div ng-repeat="image in images" ng-init="img = {}">
   <img ng-src="{{image}}" ng-init="img[$index] = imageExists(image, img, $index)" ng-show="img[$index]">
</div>

DEMO

So applying it to your code:

<div id="projects" ng-app="portfolio">
    <div id="projectsList" ng-controller="ProjectsListController as projectsList">
        <div class="projectItem" ng-repeat="projectItem in projectsList.projectsListData._embedded.projects"  ng-init="img = {}">
            <div class="project-image" ng-init="img[$index] = imageExists(projectItem._embedded.images[0].src, img, $index)" ng-show="img[$index]">
                <img
                    ng-src="{{projectItem._embedded.images[0].src}}"
                    title="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
                    alt="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
                />
            </div>
        </div>
    </div>
</div>

Place the $scope.imageExists code from above to your controller.

share|improve this answer
    
Wprks! Thank you very much! – automatix Apr 4 '15 at 12:20
    
Thank you ! good answer – Developer Aug 20 '15 at 11:45

You can use ng-if

<div class="projectItem" ng-repeat="projectItem in projectsList.projectsListData._embedded.projects" ng-if="{{projectItem._embedded.images[0].src}}">
            <div class="project-image">
                <img
                    ng-src="{{projectItem._embedded.images[0].src}}"
                    title="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
                    alt="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
                />
            </div>
        </div>
    </div>

Or you can also use ng-show/ng-hide which just doesn't show the element but would be present in DOM.

But be careful when you use ng-if as it creates its own scope.

EDIT: If the url is already set then one way is to test if the url exists using this method (or anything like this) JavaScript/jQuery check broken links , and
ng-if="UrlExists(projectItem._embedded.images[0].src)"

share|improve this answer
    
It doesn't work -- the src property is set. It's wrong (will cuase the 404 error), but it's set and projectItem._embedded.images[0].src != '' will return true for the "irrelevant" objects as well. – automatix Apr 4 '15 at 11:33
    
@automatix Check my updated answer. – maandoo Apr 4 '15 at 11:48
        <div class="project-image" ng-if="projectItem._embedded.images[0].src != ''">
            <img
                ng-src="{{projectItem._embedded.images[0].src}}"
                title="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
                alt="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
            />
        </div>
share|improve this answer
    
It doesn't work -- the src property is set. It's wrong (will cuase the 404 error), but it's set and projectItem._embedded.images[0].src != '' will return true for the "irrelevant" objects as well. – automatix Apr 4 '15 at 11:32

You could create your own image directive:

<my-image src="http://someimageurl"></my-image>

If the image exists, the directive will insert the image into the DOM. If it does not, then you can ignore it, or insert a message.

var app = angular.module('app', []);
app.directive('myImage', function() {
  return {
    restrict: 'E',
    replace:true,
    link: function(scope, element, attr) {
      var image = new Image();
      image.onload = function() {
         element.append(image);
      }
      image.onerror = function() {
         element.html('Something went wrong or the image does not exist...');
      }
      image.src = attr.src;
    }
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <my-image src="https://www.google.ca/images/srpr/logo11w.png" />
  
  <my-image src="https://server/images/doesnotexist.png" />
</div>

share|improve this answer
    
Thank you for your answer! It works for the img tag, bun in my case I want to enable/disable the whole container wrapping the image. – automatix Apr 4 '15 at 13:29

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.