if a ngSrc path resolves to a 404, is there a way

2019-01-04 06:20发布

The application I'm building requires my user to set 4 pieces of information before this image even has a chance of loading. This image is the center-piece of the application, so the broken image link makes it look like the whole thing is borked. I'd like to have another image take its place on a 404.

Any ideas? I'd like to avoid writing a custom directive for this.

I was surprised that I couldn't find a similar question, especially when the first question in the docs is the same one!

http://docs.angularjs.org/api/ng.directive:ngSrc

12条回答
Luminary・发光体
2楼-- · 2019-01-04 06:35

I suggest that you might like to use the Angular UI Utils 'if statement' directive to solve your problem, as found at http://angular-ui.github.io/. I have just used it to do exactly the same thing.

This is untested, but you could do something like:

Controller code:

$scope.showImage = function () {
    if (value1 && value2 && value3 && value4) { 
        return true;
    } else {
        return false;
    }
};

(or simpler)

$scope.showImage = function () {
    return value1 && value2 && value3 && value4;
};

HTML in View: <img ui-if="showImage()" ng-src="images/{{data.value}}.jpg" />

Or even simpler, you could just use a scope property:

Controller code:

$scope.showImage = value1 && value2 && value3 && value4;

HTML in View: <img ui-if="showImage" ng-src="images/{{data.value}}.jpg" />

For a placeholder image, just add another similar <img> tag but prepend your ui-if parameter with an exclamation (!) mark, and either make ngSrc have the path to the placeholder image, or just use a src tag as per normal ol' HTML.

eg. <img ui-if="!showImage" src="images/placeholder.jpg" />

Obviously, all of the above code samples are assuming that each of value1, value2, value3 and value4 will equate to null / false when each of your 4 pieces of information are incomplete (and thus also to a boolean value of true when they are complete).

PS. The AngularUI project has recently been broken in to sub-projects, and the documentation for ui-if seems to be missing currently (it's probably in the package somewhere though). However, it is pretty straightforward to use as you can see, and I have logged a Github 'issue' on the Angular UI project to point it out to the team too.

UPDATE: 'ui-if' is missing from the AngularUI project because it's been integrated in to the core AngularJS code! Only as of v1.1.x though, which is currently marked as 'unstable'.

查看更多
Fickle 薄情
3楼-- · 2019-01-04 06:36

Little late to the party, though I came up with a solution to more or less the same issue in a system I'm building.

My idea was, though, to handle EVERY image img tag globally.

I didn't want to have to pepper my HTML with unnecessary directives, such as the err-src ones shown here. Quite often, especially with dynamic images, you won't know if it's missing until its too late. Adding extra directives on the off-chance an image is missing seems overkill to me.

Instead, I extend the existing img tag - which, really, is what Angular directives are all about.

So - this is what I came up with.

Note: This requires the full JQuery library to be present and not just the JQlite Angular ships with because we're using .error()

You can see it in action at this Plunker

The directive looks pretty much like this:

app.directive('img', function () {
    return {
        restrict: 'E',        
        link: function (scope, element, attrs) {     
            // show an image-missing image
            element.error(function () {
                var w = element.width();
                var h = element.height();
                // using 20 here because it seems even a missing image will have ~18px width 
                // after this error function has been called
                if (w <= 20) { w = 100; }
                if (h <= 20) { h = 100; }
                var url = 'http://placehold.it/' + w + 'x' + h + '/cccccc/ffffff&text=Oh No!';
                element.prop('src', url);
                element.css('border', 'double 3px #cccccc');
            });
        }
    }
});

When an error occurs (which will be because the image doesn't exist or is unreachable etc) we capture and react. You can attempt to get the image sizes too - if they were present on the image/style in the first place. If not, then set yourself a default.

This example is using placehold.it for an image to show instead.

Now EVERY image, regardless of using src or ng-src has itself covered in case nothing loads up...

查看更多
Bombasti
4楼-- · 2019-01-04 06:40

If image is 404 or image is null empty whatever there is no need for directives you can simply use ng-src filter like this :)

<img ng-src="{{ p.image || 'img/no-image.png' }}" />
查看更多
在下西门庆
5楼-- · 2019-01-04 06:44

Here's a solution I came up with using native javascript. I'm checking if the image is broken then adding a class to the image just in case and changing the source.

I got part of my answer from a Quora answer http://www.quora.com/How-do-I-use-JavaScript-to-find-if-an-image-is-broken

app.directive('imageErrorDirective', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element[0].onerror = function () {
                element[0].className = element[0].className + " image-error";
                element[0].src = 'http://img3.wikia.nocookie.net/__cb20140329055736/pokemon/images/c/c9/702Dedenne.png';
            };
        }
    }
});
查看更多
霸刀☆藐视天下
6楼-- · 2019-01-04 06:48

Is there a specific reason you can't declare the fallback image in your code?

As I understand, you have two possible cases for your image source:

  1. Correctly set pieces of information < 4 = Fallback image.
  2. Correctly set pieces of information == 4 = Generated URL.

I think this should be handled by your app - if the correct URL cannot currently be determined, instead pass a loading/fallback/placeholder image URL.

The reasoning is that you never have a 'missing' image, because you have explicitly declared the correct URL to display at any point in time.

查看更多
相关推荐>>
7楼-- · 2019-01-04 06:48

This will allow only to loop twice, to check if the ng-src doesn't exist else use the err-src, this prevents the continues looping.

(function () {
    'use strict';
    angular.module('pilierApp').directive('errSrc', errSrc);

    function errSrc() {
        return {
            link: function(scope, element, attrs) {
             element.error(function () {
                // to prevent looping error check if src == ngSrc
                if (element.prop('src')==attrs.ngSrc){
                     //stop loop here
                     element.prop('src', attrs.errSrc);
                }              
            });
            }
        }
    }
})();
查看更多
登录 后发表回答