ngSrc 경로가 404로 해석되면 기본값으로 대체하는 방법이 있습니까?


129

내가 만들고있는 응용 프로그램은이 이미지가로드되기 전에 사용자가 4 가지 정보를 설정해야합니다. 이 이미지는 응용 프로그램의 중심 부분이므로 이미지 링크가 끊어지면 전체가 멍한 것처럼 보입니다. 404에서 다른 이미지를 사용하고 싶습니다.

어떤 아이디어? 이에 대한 사용자 지정 지시문 작성을 피하고 싶습니다.

비슷한 질문을 찾을 수 없다는 사실에 놀랐습니다. 특히 문서의 첫 번째 질문이 같은 경우에 특히 그렇습니다!

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


이것은 관련이있을 수 있습니다 : stackoverflow.com/q/13781685/1218080
홀로그램 원리

답변:


252

이미지 로딩 오류를보고 src를 교체하는 것은 매우 간단한 지시어입니다. (플 런커)

HTML :

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

자바 스크립트 :

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 속성을 업데이트하지 않는다는 것입니다.


URL이 깨지면 (404) 잘 작동하지만 빈 문자열이면 ng-src가 자동으로 오류를 삼킨다.
Stephen Patten

2
빈 문자열이 모델에 유효하지 않은 경우 ng-src로 바인딩하는 표현식이 빈 문자열을 반환하지 않도록하십시오.
Justin Lovero

의 지원 사용하도록 업데이트 스크립트 src에 대한 속성 err-src이미지 : plnkr.co/edit/b05WtghBOHkxKdttZ8q5
라이언 슈마허

@JustinLovero 나는 그것이 각도의 버그라고 생각하고 그것을보고했다. 문제는 값이 비어 있으면 ngSrc가 src 속성을 설정하지 않는다는 것입니다. 예를 들어 전화를 표시하고 이미지 URL이없는 아약스가있는 다른 전화를로드하는 경우 실제로 문제가 될 수 있습니다. 이전 전화의 이미지는 계속 표시되지만 오류 또는 자리 표시자가 더 적절할 것입니다. 예, 모델에서 처리 할 수 ​​있지만 오래된 이미지를 남기는 동작은 오류를 표시하는 것보다 더 잘못이라고 생각합니다.
Jason Goemaat

@JasonGoemaat, 깨진 이미지를 텍스트로 바꾸려면 어떻게해야합니까?
simeg

48

파티에 조금 늦었지만, 내가 구축하는 시스템에서 거의 같은 문제에 대한 해결책을 찾았습니다.

그러나 내 생각은 모든 이미지 img태그를 전 세계적으로 처리하는 것이 었습니다 .

나는 여기에 표시된 것과 HTML같은 불필요한 지시어로 내 고추를 피우고 싶지 않았습니다 err-src. 특히 동적 이미지의 경우 너무 늦을 때까지 이미지가 누락되었는지 알 수 없습니다. 오프-기회에 추가 지시문을 추가하면 이미지가 과도하게 보입니다.

대신 기존 img태그를 확장합니다 . 실제로 Angular 지시문이 전부입니다.

그래서 이것은 내가 생각해 낸 것입니다.

참고 :이를 위해서는 JQlite Angular뿐만 아니라 전체 JQuery 라이브러리가 있어야합니다..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
아주 좋은 해결책! 이걸 맨 위로 투표합시다!
Matthijs

1
이것은 내가 말해야 할 매우 아름답습니다. 실제로 해결되지 않으면 이미지가 전혀 표시되는 것을 원하지 않으므로 사용했습니다. element.css ( "display", "none"); 완전히 숨기려면
폼페이우스

1
nice :) 또는 element.remove ();를 사용하여 DOM에서 완전히 제거 할 수 있습니다. :)
Darren Wainwright

잘 작동합니다, 감사합니다!
ecorvo

솔루션을 약간 편집 했으므로 경로가 비어있을 때도 작동합니다. stackoverflow.com/a/35884288/2014288
andrfas

21

Jason 솔루션을 확장하여로드 오류 또는 빈 소스 문자열의 두 경우를 모두 포착하려면 시계를 추가하면됩니다.

HTML :

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

자바 스크립트 :

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

    }
  }
});

2
멋진 코드이지만 ng-if템플릿 (빈 src 문자열)에서 쉽게 확인할 수있는 것에 대한 시계를 추가하는 것은 과잉 인 것 같습니다.
alonisser

ngSrc를 자신의 지시문으로 바꾸고 원하는 경우 별도의 errSrc 지시문 대신 errSrc를 사용하도록 오류시 바인드를 설정 한 것처럼 보입니다. attrs.$observe('ngSrc', function(value) {...});ngSrc가 $ watch 대신 내부적으로 사용하는 것을 사용할 수 있습니다 .
Jason Goemaat

공백의 전체 문제점은 값이 공백 인 경우 ngSrc가 src 속성을 업데이트하지 않기 때문에 ngSrc를 대체하는 고유 한 지시문이있는 경우 공백 점검이 필요하지 않습니다.
Jason Goemaat

1
@Pokono-현재 'src'속성이 'errSrc'와 같은지 여부를 오류 함수 내부에서 확인할 수 있습니다.
user2899845

1
@BiswasKhayargoli-구독 취소 호출을 추가하여 초기로드 후 처리 비용이 발생하지 않음
user2899845

11
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}}" />

jQuery를 사용하지 않고 문제를 해결하기 때문에 이것이 정답이라고 생각합니다.
Gregra

10

이미지가 404이거나 이미지가 비어 있으면 지시문이 필요하지 않은 경우 다음과 같이 ng-src 필터를 사용할 수 있습니다. :)

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

2
아니요, p.image가 AJAX 호출에서 404를 반환하면이를 'true'로 취급하고 두 번째 img / no-image.png로 이동하지 않습니다.
James Gentes

2
@JamesGentes-그것은 사실이 아닌 것 같습니다. 이 ng-src 사용은 표시된대로 정확하게 작동합니다. 그리고 훨씬 간단합니다.
shanemgrey

@shaneveeg 감사합니다. 흥미 롭습니다. 백엔드가 다른지 궁금합니다. Express로 Node를 실행 중입니다. 아마 다르게 처리합니다.
James Gentes

2
@JamesGentes-이전 의견 수정. OP는 모델이 반환 한 유효한 URI가있을 때 해결책을 찾고 있지만 따라 올 때 404를 찾습니다. 이 경우이 솔루션이 작동하지 않아 이미지가 깨집니다. 각도가 이미지 값에 대해 아무것도 반환하지 않으면 폴백을 올바르게 선택합니다.
shanemgrey

Laravel을 사용하고 있으며 404, null 또는 비어있는 경우 나에게 완벽하게 작동합니다. 그러나 Express는 404와 같은 코드 응답 대신 어떤 종류의 오류를 반환하므로 서버 프레임 워크에 따라 다를 수 있습니다.
NeoNe

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">

2
이 겨-SRC가 볼 수있는 반면이 문자열 (참 /의 거짓)로 "team.logo"를 평가할 때 {{team.logo}}이 사실로는 404를 반환하는 경우에도, 올
제임스 씨족


1

코드에서 대체 이미지를 선언 할 수없는 특별한 이유가 있습니까?

내가 이해하는 것처럼 이미지 소스에 대해 두 가지 가능한 경우가 있습니다.

  1. 정보 조각 <4 = 대체 이미지를 올바르게 설정하십시오.
  2. 정보를 올바르게 설정 == 4 = 생성 된 URL.

올바른 URL을 확인할 수없는 경우 대신로드 / 폴백 / 자리 표시 자 이미지 URL을 전달하십시오.

특정 시점에 표시 할 올바른 URL을 명시 적으로 선언했기 때문에 '누락 된'이미지가 없기 때문입니다.


죄송합니다. 4 개의 값이 모두 설정되어 있어도 URL은 여전히 ​​404 (사용자는 폴더를 추가 할 수 있음) 일 수 있습니다. 그 동안 모든 값이 올 때 URL의 응답 헤더를 확인하는 기능을 추가했습니다. 설정됩니다. 여전히 특별한 대우없이 이것을 처리하는 것이 좋을 것입니다. 나는 이것을 다시 보게 될 것입니다 :)
will_hardin

1
쿨, 당신은 대답으로 표시하고 미래에 검색하는 사람에게 허용으로 표시해야합니다.
Alex Osborn

1

http://angular-ui.github.io/에있는 것처럼 Angular UI Utils 'if statement'지시문을 사용하여 문제를 해결하고 싶을 것 입니다. 방금 똑같은 일을하기 위해 사용했습니다.

이것은 테스트되지 않았지만 다음과 같이 할 수 있습니다.

컨트롤러 코드 :

$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 속성을 사용할 수 있습니다.

컨트롤러 코드 :

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

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

자리 표시 자 이미지의 경우 다른 유사한 <img>태그를 추가 ui-if하고 느낌표 ( !) 표시로 매개 변수를 추가 하고 ngSrc에 자리 표시 자 이미지의 경로를 지정하거나 src일반 ol 'HTML에 따라 태그를 사용하십시오 .

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

물론, 위의 코드 샘플의 모든 값 1, 값, VALUE3 및 VALUE4 각각 동일시 것으로 가정합니다 null/ false정보를 귀하의 4 개의 각 (의 부울 값도 따라서 불완전한 경우 true가 완료되면).

추신. AngularUI 프로젝트는 최근에 하위 프로젝트로 분류되었으며 ui-if현재 설명서 가 누락 된 것 같습니다 (아마도 패키지에있을 수 있습니다). 그러나 당신이 볼 수 있듯이 사용하는 것은 매우 간단하며, Angular UI 프로젝트에 Github '문제'를 기록하여 팀에게도 지적했습니다.

업데이트 : 핵심 AngularJS 코드에 통합되어 있기 때문에 AngularUI 프로젝트에서 'ui-if'가 누락되었습니다! 그러나 현재 '불안정한'것으로 표시된 v1.1.x에서만.


ng-if핵심 btw에 넣었습니다 (실수하지 않으면 1.1.5 기준).
홀로그램 원리

1

다음은 네이티브 자바 스크립트를 사용하여 얻은 솔루션입니다. 이미지가 깨 졌는지 확인하고 소스를 변경하는 경우를 대비하여 이미지에 클래스를 추가합니다.

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

0

내 자신의 솔루션을 생각해 냈습니다. src 또는 ngSrc가 비어 있고 img가 404를 반환하면 이미지를 교체합니다.

(@Darren 솔루션의 포크)

directive('img', function () {
return {
    restrict: 'E',        
    link: function (scope, element, attrs) {   
        if((('ngSrc' in attrs) && typeof(attrs['ngSrc'])==='undefined') || (('src' in attrs) && typeof(attrs['src'])==='undefined')) {
            (function () {
                replaceImg();
            })();
        };
        element.error(function () {
            replaceImg();
        });

        function replaceImg() {
            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=No image';
            element.prop('src', url);
        }
    }
}
});

0

이렇게하면 ng-src가 존재하지 않는지 확인하기 위해 두 번만 반복 할 수 있으며 err-src를 사용하면 계속 반복되지 않습니다.

(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);
                }              
            });
            }
        }
    }
})();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.