最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - show alternate image if img src is not found - knockout - Stack Overflow

programmeradmin0浏览0评论

I have this piece of code.

<img data-bind="attr: {src: 'imagePath'}, style: { 'background-image': 'url('imagePath')' }" class="img-responsive">

The problem is it is showing two images. One is the image ing from src and other one ing from background image. My goal was to enable the background image when the src image is not available.

I have this piece of code.

<img data-bind="attr: {src: 'imagePath'}, style: { 'background-image': 'url('imagePath')' }" class="img-responsive">

The problem is it is showing two images. One is the image ing from src and other one ing from background image. My goal was to enable the background image when the src image is not available.

Share Improve this question asked Feb 15, 2016 at 20:22 user2281858user2281858 1,99710 gold badges48 silver badges88 bronze badges 4
  • Why don't you only use the src attribute, and wire it to an observable that will resolve the image source when it bees available? – cl3m Commented Feb 15, 2016 at 20:25
  • Default to showing the fallback image, and replace it if and when the other image is found. – Gary Hayes Commented Feb 15, 2016 at 20:45
  • Using a background image as the alternate will create some problems, e.g., it will still display a broken image icon and you will need to set the height and width. That is why using only the src seems a better solution. – Yogi Commented Feb 15, 2016 at 21:02
  • Just wondering if my answer did, in fact, answer your question? – JDR Commented Feb 20, 2016 at 23:24
Add a ment  | 

3 Answers 3

Reset to default 9

What you can do is create a custom binding, let's call it safeSrc.

In this binding, you listen to the load and error events of your image - rendering your image if it's loaded successfully and rendering a fallback if it is not.

In practice, it could look like the following:

ko.bindingHandlers.safeSrc = {
  update: function(element, valueAccessor) {
    var options = valueAccessor();
    var src = ko.unwrap(options.src);
    $('<img />').attr('src', src).on('load', function() {
      $(element).attr('src', src);
    }).on('error', function() {
      $(element).attr('src', ko.unwrap(options.fallback));
    });
  }
};

And then, you can apply the binding like this:

<img alt="Foo" data-bind="safeSrc: {src: imageObservable, fallback: 'https://example./fallback.png'}" />

Note that this presumes you're using jQuery - but you can easily rewrite the event listener.

Finally, I would also like to say that you should be rendering a different src instead of the background image - unless you have a specific reason to require one?

Either way, you can simply change the line $(element).attr('src', ko.unwrap(options.fallback)); to $(element).css('background-image', 'url(' + ko.unwrap(options.fallback) + ')');.

JS Fiddle Demo

Here, you can see it all in action: https://jsfiddle/13vkutkv/2/

(EDIT: I replaced the cheeky hotlink to the Knockout JS logo with Placehold.it)

P.S.: Depending on how you wish to interact with the element in future (interacting with/updating the binding), you may wish to use applyBindingsToNode (i.e. the Knockout-way), rather than manipulating the src attribute directly on the DOM element.

To show alternate image if img src is not found make alternate image link in your server logic and use only src: 'imagePath' in your front-end

Or if it is important to do it in front-end, you should look at this post: Display alternate image

I always check my images with a deferred object to be sure they will load. This is using the jquery deferred method, but you could use any deferred library. I coded this from memory, so there may be some errors.

<img data-bind="attr: {src: $root.imagePath()}, style: { 'background-image': 'url('imagePath')' }" class="img-responsive">

var myController = function()
{
    var self = this;
    this.imagePath = ko.observable('myPath.png'); // Make the image url an observable
    var getImagePath = function(path)
    { 
        var imagePath = this.imagePath();
        isLoaded(imagePath).done(function(result)
        {
            // The image will load fine, do nothing.
        }).fail(function(e)
        {
            self.imagePath('defaultImageOnFail.png'); // replace the image if it fails to load
        });
    };
    getImagePath();
};

var isLoaded = function(img)
{
    var deferred = new $.Deferred();
    var imgObj = $("<img src='"+img+"'/>");
    if(imgObj.height > 0 || imgObj.width > 0)
    {
        deferred.resolve(true);
    }
    else
    {
        imgObj.on("load", function(e)
        {
            deferred.resolve(true);
        });
        imgObj.on("error", function(e)
        {
            console.info("VoteScreenController.isLoaded URL error");
            deferred.reject();
        });
    }
    return deferred.promise();
};
发布评论

评论列表(0)

  1. 暂无评论