21

I want to show user image if image exist, like :

<img alt="user_image" src="/images/profile_images/{{result.image}}">

And if user image not available then should show default image , Like

<img alt="user_image" src="/images/default_user.jpg">

How can I do this through angularjs in html page ?

Arvind Kushwaha
  • 759
  • 2
  • 10
  • 18
  • By image not exists you mean an HTTP code 404 returned by the server? If this is the case, I don't think it is possible, since who actually handles the image is the browser, Angular just build the URL. What you can do is make the web server return a default image if the specified one does not exists. – Vinícius Gobbo A. de Oliveira Feb 05 '15 at 14:00

6 Answers6

31

You could create a directive checkImage to check if the image really exist:

<img check-image ng-src="{{img}}" alt="Image" width="100%"  >

Directive:

myApp.directive('checkImage', function($http) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            attrs.$observe('ngSrc', function(ngSrc) {
                $http.get(ngSrc).success(function(){
                    alert('image exist');
                }).error(function(){
                    alert('image not exist');
                    element.attr('src', '/images/default_user.jpg'); // set default image
                });
            });
        }
    };
});

See the demo http://jsfiddle.net/manzapanza/dtt1z5p8/

manzapanza
  • 6,087
  • 4
  • 39
  • 48
  • When I using this it will always set the default image even though I got a source, how come? – Rafael May 17 '16 at 13:34
  • @S.RLobato probably because of CORS issues, was the image on a different domain to the one you were loading your script from? – Horse Jan 09 '17 at 14:12
  • @SaaksshiTyagi: If you think you have [a better solution](https://stackoverflow.com/review/suggested-edits/17252100), you should post it as a separate answer. – Ilmari Karonen Sep 06 '17 at 14:45
19

You can pass in an expression to the alt attribute:

<img alt="{{user_image}}" src="/images/profile_images/{{result.image}}">

Edit: Doh, misread your question. In your controller (or the service which provides the image to the controller), you can set result.image to the user's image or the default image.

Another option is to use conditional logic in ng-src:

<img ng-src="{{ result.image || 'default_user.jpg' }}"/>

This will set the src to result.image if it exists, otherwise to the default.

Personally, I like the first option better since it keeps logic out of the view, but I bet you could find someone who would argue that it belongs in the view since it is view logic.

Edit 2: here is a plnkr: http://plnkr.co/edit/vfYU8T3PlzjQPxAaC5bK?p=preview

Noel
  • 3,288
  • 1
  • 23
  • 42
  • No, I want to change value of 'src' not 'alt'. how can I check if {{result.image}} is empty or having some value..? – Arvind Kushwaha Feb 05 '15 at 14:02
  • this works perfectly if the `result.image == null`, but I think the author wants to know the actual image exists on the server – A-Sharabiani Sep 17 '15 at 14:54
  • If the image doesn't exist on the server, the angular service responsible for retrieving the image could handle the 404 response and set result.image to null. – Noel Sep 17 '15 at 15:45
  • 1
    I like your answer because its a lot less code and a lot easier to read if its someone else his code. And in my case, it achieved what i wanted to achieve. – Vahx Jan 15 '16 at 14:19
  • 1
    well it wont work if link in ng-src is invalid or image has been removed from that url. better way will be : https://stackoverflow.com/questions/92720/jquery-javascript-to-replace-broken-images?lq=1 – Sheelpriy Jun 09 '16 at 05:44
7

The previously mentioned solutions will double the HTTP requests. Every image will be loaded twice!

This solution does not reload the image just to see if it exists:

myApp.directive('checkImage', function() {
   return {
      link: function(scope, element, attrs) {
         element.bind('error', function() {
            element.attr('src', '/images/default_user.jpg'); // set default image
         });
       }
   }
});
mvermand
  • 5,829
  • 7
  • 48
  • 74
  • this is a AngularJS directive and won't work in Angular 2 / 4 just like this, but the concept remains. You could port this to Angular code. – mvermand Jun 30 '17 at 09:59
5
App.directive('checkImage', function ($q) {
return {
    restrict: 'A',
    link: function (scope, element, attrs) {
        attrs.$observe('ngSrc', function (ngSrc) {
            var deferred = $q.defer();
            var image = new Image();
            image.onerror = function () {
                deferred.resolve(false);
                element.attr('src', BASE_URL + '/assets/images/default_photo.png'); // set default image
            };
            image.onload = function () {
                deferred.resolve(true);
            };
            image.src = ngSrc;
            return deferred.promise;
        });
    }
};

});

Mehul
  • 161
  • 2
  • 4
1

If you are using Ionic 2 you can try this, it's worked for me:

<img src="{{data.imgPath || 'assets/img/empty.png'}}" >
0

Just for fun , Angular 2 is on the way . According the specification ngIf may solve in any directive . There is no need to complex directives . Build a class checks for the result object which have method check image is exists as @manzapanza did. Build a class definition as follows :

<div *ngIf=result.isImageExists()>
<img [src]="result.image" /> 
</div> 
<div *ngIf=!result.isImageExists()>
<img [src]="result.defaultImage" /> 
</div> 

I think new angular is better and more clear. Hope Helpes!!;

Osman Corluk
  • 325
  • 1
  • 3
  • 12