使用AngularJS ng-src实现回退(默认)图像

14

我正在尝试使用从模态框返回的数据设置图片源。这是在一个ng-repeat循环内:

<div id="divNetworkGrid">
    <div id="{{network.id}}" ng-repeat="network in networks">
        <span>
            <table>
                <tr>
                    <td class="imgContainer">
                        <img ng-src="{{ ('assets/img/networkicons/'+ network.actual + '.png') || 
                                         'assets/img/networkicons/default.png' }}"/>
                    </td>
                </tr>
            </table>
        </span>
    </div>
</div>
显而易见,当network.actual模型属性返回为null时,我希望使用default.png。但是我的代码没有选用默认图像,尽管第一张图片在可用时可以正常显示。我确定这是某些语法问题,但找不出错在哪里。

我经常想知道如何做到这一点,并尝试了像你一样的方法,但似乎从未奏效!好问题! - SM3RKY
6个回答

31

我刚刚发现,在 img 标签中可以同时使用 ng-srcsrc 属性。如果 ng-src 失败(变量不存在等情况),它将自动回退到 src 属性。


3
如果您不想写更多的代码,我认为解决方案会更好。 - Parijat

19

我想发生的情况是,即使network.actual为null,src仍然返回404。例如,第一个值:

('assets/img/networkicons/'+network.actual+'.png')

会计算出一个404的src URL,类似于('assets/img/networkicons/null.png')。因此,在OR选择中,它是真实的,但资源是404。在这种情况下,您可以通过onError设置回退值,例如:

<img ng-src="{{('assets/img/networkicons/'+network.actual+'.png')}}" onerror="this.src='assets/img/networkicons/default.png'" />

CodePen展示用例 - http://codepen.io/jpost-vlocity/pen/zqqerL


1
如果+network.actual+变量存在但图像不存在,那么这就是完美的! - Fergus
1
我认为最佳解决方案是... - Sergey Mell
干净、简单、整洁。运行良好。 - Aine Evans
谢谢。优雅简洁的解决方案。 - Chirag Parmar

15
angular.module('fallback',[]).directive('fallbackSrc', function () {
    return{
        link: function postLink(scope, element, attrs) {
            element.bind('error', function () {
                angular.element(this).attr("src", attrs.fallbackSrc);
            });
        }
    }
});

<img ng-src="{{url}}" fallback-src="default-image.jpg"/>

angular.module('fallback', []).directive('actualSrc', function () {
    return{
        link: function postLink(scope, element, attrs) {
            attrs.$observe('actualSrc', function(newVal, oldVal){
                 if(newVal != undefined){
                     var img = new Image();
                     img.src = attrs.actualSrc;
                     angular.element(img).bind('load', function () {
                         element.attr("src", attrs.actualSrc);
                     });
                 }
            });

        }
    }
});

<img actual-src="{{url}}" ng-src="default.jpg"/>

链接


一开始我很不愿意尝试这个,因为我认为肯定有更简单的解决方案。但是,在尝试了许多建议后,发现没有一个完美地解决问题,这绝对是最好的一个。谢谢! - newman
@miliu 很高兴能帮到你 :) - Subash Selvaraj
1
小错误:第一个示例应该使用fallback-src作为HTML代码的属性(或fallBackSrc作为指令名称)。否则是个很好的解决方案! - wal5hy

10

使用ng-src的有趣方法。我还没有测试过该表达式的处理方式,但我建议以更稳定的方式进行:

<img ng-src="{{ networkIcon }}" />

并且在你的控制器中:

$scope.networkIcon = network.actual ? 'assets/img/networkicons/' + network.actual + '.png' : 'assets/img/networkicons/default.png';

编辑:仅澄清一下,我并不建议将图像源直接绑定到作用域中,而是将图像回退逻辑移出视图。在我的应用程序中,我经常在检索数据的服务中或在服务器本身上处理它,并发送图像URL,因此客户端只需要担心一个属性。

针对repeater的编辑:

angular.forEach($scope.networks, function(network) {
  network.icon = network.actual ? 'assets/img/networkicons/' + network.actual + '.png' : 'assets/img/networkicons/default.png';
});

<tr ng-repeat="network in networks">
  <td><img ng-src="{{ network.icon }}" /></td>
</tr>

1
我之前应该说明一下,但是network.actual实际上在ng-repeat中。network是networks模型的迭代。所以这个选项对我来说行不通,很遗憾... - nikjohn
是的,我的编辑段落中提到我在检索数据的服务中执行此操作。因此,在绑定到重复器之前,请迭代您的数据并替换(或附加)图像源。 - Terry
我已经更新了我的答案,并提供了一个示例,说明如何在数据到达中继器之前修改数据。 - Terry

8
<div id="divNetworkGrid">
                <div id="{{network.id}}" ng-repeat="network in networks">
                    <span>
                        <table>
                            <tr>
                                <td class="imgContainer">
                                    <img ng-src="{{'assets/img/networkicons/'+(network.actual || 'default' )+'.png'}}"/>
                                </td>
                            </tr>
                        </table>
                    </span>
                </div>
            </div>

如果所查询的变量未定义,内联或将起作用。以上内容将解决您的问题。


5
您可以在 OR 运算符之后提供备用图片,方法如下:
{{ book.images.url || 'Images/default.gif' }}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接