如果ngSrc路径解析为404,有没有办法回退到默认值?

时间:2013-04-30 22:59:13

标签: angularjs angularjs-directive imagesource

我正在构建的应用程序要求我的用户在此图像甚至有可能加载之前设置4条信息。这个图像是应用程序的中心部分,因此破碎的图像链接使得整个事物看起来像是被塞满了。我想让另一张图片取代404。

有什么想法吗?我想避免为此编写自定义指令。

我很惊讶我找不到类似的问题,特别是当文档中的第一个问题是同一个问题时!

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

12 个答案:

答案 0 :(得分:252)

这是一个非常简单的指令,用于观察加载图像和替换src时出错。 (Plunker)

HTML:

<img ng-src="smiley.png" err-src="http://google.com/favicon.ico" />

使用Javascript:

var app = angular.module("MyApp", []);

app.directive('errSrc', function() {
  return {
    link: function(scope, element, attrs) {
      element.bind('error', function() {
        if (attrs.src != attrs.errSrc) {
          attrs.$set('src', attrs.errSrc);
        }
      });
    }
  }
});

如果要在ngSrc为空时显示错误图像,可以添加(Plunker)

attrs.$observe('ngSrc', function(value) {
  if (!value && attrs.errSrc) {
    attrs.$set('src', attrs.errSrc);
  }
});

问题是如果值为空,ngSrc不会更新src属性。

答案 1 :(得分:48)

虽然我在建立的系统中提出了或多或少相同问题的解决方案。

但我的想法是全局处理每张图片img

我不想让我的HTML加上不必要的指令,例如此处显示的err-src指令。很多时候,特别是对于动态图像,你不知道它是否会丢失,直到它为时已晚。在图像丢失的情况下添加额外的指令对我来说似乎有点过分了。

相反,我扩展了现有的img标签 - 实际上,它是Angular指令的全部内容。

所以 - 这就是我想出来的。

注意:这需要完整的JQuery库,而不仅仅是JQlite Angular,因为我们正在使用.error()

您可以在此Plunker

中看到它的实际效果

该指令看起来非常像:

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');
            });
        }
    }
});

当发生错误(这是因为图像不存在或无法访问等)时,我们会捕获并做出反应。您也可以尝试获取图像大小 - 如果它们首先出现在图像/样式上。如果没有,那么设置一个默认值。

此示例使用placehold.it来显示图像。

现在,无论使用src还是ng-src,每张图片都会被覆盖,以防无法加载......

答案 2 :(得分:21)

要扩展Jason解决方案以捕获加载错误或空源字符串的情况,我们只需添加一个监视。

HTML:

<img ng-src="smiley.png" err-src="http://google.com/favicon.ico" />

使用Javascript:

var app = angular.module("MyApp", []);

app.directive('errSrc', function() {
  return {
    link: function(scope, element, attrs) {

      var watcher = scope.$watch(function() {
          return attrs['ngSrc'];
        }, function (value) {
          if (!value) {
            element.attr('src', attrs.errSrc);  
          }
      });

      element.bind('error', function() {
        element.attr('src', attrs.errSrc);
      });

      //unsubscribe on success
      element.bind('load', watcher);

    }
  }
});

答案 3 :(得分:10)

如果图像为404或图像为空,无论指令是什么,您只需使用ng-src过滤器:)

<img ng-src="{{ p.image || 'img/no-image.png' }}" />

答案 4 :(得分:10)

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;
            });
        }
    };
});
HTML中的

<img class="img-circle" check-image ng-src="{{item.profileImg}}" />

答案 5 :(得分:8)

我使用类似的东西,但它假设team.logo有效。如果未设置“team.logo”或为空,则强制默认。

<img ng-if="team.logo" ng-src="https://api.example.com/images/{{team.logo}}">
<img ng-hide="team.logo" ng-src="img/default.png">

答案 6 :(得分:2)

你不需要角度,甚至CSS或JS。如果你愿意,你可以将这个答案(链接)包装在一个简单的指令中,使它更简单,比如或者什么,但这是一个非常简单的过程......只需将它包装在一个对象标签中......

How to hide image broken Icon using only CSS/HTML (without js)

答案 7 :(得分:1)

您是否有特定原因无法在代码中声明后备图片?

据我了解,您的图像源有两种可能的情况:

  1. 正确设置信息&lt; 4 =后备图像。
  2. 正确设置信息== 4 =生成的网址。
  3. 我认为这应由您的应用处理 - 如果当前无法确定正确的网址,请传递加载/后备/占位符图片网址。

    原因是您从未有过“丢失”的图片,因为您已明确声明要在任何时间点显示的正确网址。

答案 8 :(得分:1)

我建议您可以使用Angular UI Utils的“if语句”指令来解决您的问题,如http://angular-ui.github.io/所示。我刚用它来做同样的事情。

这是未经测试的,但您可以执行以下操作:

控制器代码:

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

(或更简单)

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

视图中的HTML:<img ui-if="showImage()" ng-src="images/{{data.value}}.jpg" />

甚至更简单,您可以使用范围属性:

控制器代码:

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

视图中的HTML:<img ui-if="showImage" ng-src="images/{{data.value}}.jpg" />

对于占位符图片,只需添加其他类似<img>标记,但在ui-if参数前加上感叹号(!)标记,并使ngSrc具有占位符图片的路径,或者只按照普通的'HTML。

使用src标记

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

显然,所有上述代码示例都假设当您的4条信息中的每条信息都不完整时,value1,value2,value3和value4中的每一条都等同于null / false(因此当它们完成时也是一个布尔值true

PS。 AngularUI项目最近被分解为子项目,目前似乎缺少ui-if的文档(虽然它可能在某个地方的软件包中)。但是,正如您所看到的那样,使用它非常简单,我已经在Angular UI项目中记录了一个Github'问题',以便向团队指出它。

更新:AngularUI项目中缺少'ui-if',因为它已集成到核心AngularJS代码中!仅限于v1.1.x,目前标记为“不稳定”。

答案 9 :(得分:1)

这是我使用原生javascript提出的解决方案。我检查图像是否坏了然后在图像中添加一个类以防万一并更改源。

我从Quora回答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';
            };
        }
    }
});

答案 10 :(得分:0)

想出了我自己的解决方案。 如果src或ngSrc为空,它将替换图像,如果img返回404。

(@Darren解决方案的分支)

    public JsonResult SaveApplicatDetail()
    {
        try
        {
            var resolveRequest = HttpContext.Request;
            TicketMasterModel TMM = new TicketMasterModel();
            resolveRequest.InputStream.Seek(0, SeekOrigin.Begin);
            string jsonString = new StreamReader(resolveRequest.InputStream).ReadToEnd();
            if (jsonString != null)
            {
                TMM = (TicketMasterModel)js.Deserialize(jsonString, typeof(TicketMasterModel));
            }
            int TicketId = 0;
            using (var db = new UnitOfWork())
            {
                DAL.tbl_TrnTicketMaster TM = new DAL.tbl_TrnTicketMaster();
                TM.ApplicantName = TMM.ApplicantName;
                TM.ApplicantMobile = TMM.ApplicantMobile;
                TM.ApplicantEmailId = TMM.ApplicantEmailId;
                TM.ApplicantFHName = TMM.ApplicantFHName;

                TM.FK_CompanyId = 1;
                TM.CustomerId = UserSession.UserId;
                TM.IsSubmissionLocked = false;
                TM.CreatedBy = UserSession.UserId;
                db.tbl_TrnTicketMaster.Insert(TM);

                TicketId = TM.PK_TicketId;
            }
            return Json(TicketId, JsonRequestBehavior.AllowGet);
        }
        catch (Exception)
        {
            throw;
        }
    }

答案 11 :(得分:0)

这将只允许循环两次,以检查ng-src是否存在,否则使用err-src,这可以防止继续循环。

<form name="bidForm" id="bidForm">
  <input type="text" name="bidId" id="bidId"/>
  <input type="text" name="bidAmount" id="bidAmount"/>
  <input type="text" name="highBid" id="highBid"/>
  <textarea name="bidList" id="bidList"></textarea>
</form>