अगर एक ngSrc पथ 404 के लिए हल हो जाता है, तो क्या डिफ़ॉल्ट में वापसी करने का एक तरीका है?


129

मैं जो एप्लिकेशन बना रहा हूं उसके लिए मेरे उपयोगकर्ता को इस छवि से पहले ही जानकारी के 4 टुकड़े सेट करने की आवश्यकता होती है, यहां तक ​​कि लोड करने का मौका भी हो। यह छवि एप्लिकेशन का केंद्र-टुकड़ा है, इसलिए टूटी हुई छवि लिंक ऐसा दिखता है कि यह पूरी तरह से बोर हो गया है। मैं एक और छवि को 404 पर रखना चाहता हूं।

कोई विचार? मैं इसके लिए एक कस्टम निर्देश लिखने से बचना चाहूंगा।

मुझे आश्चर्य हुआ कि मुझे एक समान प्रश्न नहीं मिला, खासकर जब डॉक्स में पहला प्रश्न एक ही है!

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


यह प्रासंगिक हो सकता है: stackoverflow.com/q/13781685/1218080
होलोग्राफिक-सिद्धांत

जवाबों:


252

यह एक छवि लोड करने और src को बदलने के लिए एक बहुत ही सरल निर्देश है। (Plunker)

एचटीएमएल:

<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 रिक्त हो तो आप इसे (प्लंकर) जोड़ सकते हैं :

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

समस्या यह है कि यदि मान रिक्त है, तो ngSrc src विशेषता को अद्यतन नहीं करता है।


अच्छी तरह से काम करता है अगर url टूट गया है (404), लेकिन अगर यह एक खाली स्ट्रिंग ng-src चुपचाप त्रुटि को निगलता है।
स्टीफन पैटन

2
यदि एक खाली स्ट्रिंग आपके मॉडल के लिए मान्य नहीं है, तो इसे बनाएं ताकि आप जिस अभिव्यक्ति के साथ एनजी-एसकेबी के लिए बाध्य कर रहे हैं वह खाली स्ट्रिंग वापस न आए।
जस्टिन लोवरो

छवि के srcलिए विशेषता के उपयोग का समर्थन करने के लिए अद्यतित स्क्रिप्ट err-src: plnkr.co/edit/b05WtghBOHkxKdttZ8q5
रयान शूमाकर

@JustinLovero मैं इसे कोणीय में एक बग मानता हूं और इसकी सूचना दी। समस्या यह है कि यदि मान रिक्त है, तो ngSrc src विशेषता को सेट नहीं करेगा। यह वास्तव में एक समस्या हो सकती है यदि उदाहरण के लिए आप एक फोन प्रदर्शित कर रहे हैं और एक अन्य फोन को अजाक्स के साथ लोड कर रहे हैं जो एक छवि यूआरएल को याद कर रहा है। पुराने फोन की छवि प्रदर्शित होती रहेगी, लेकिन मुझे लगता है कि त्रुटि या प्लेसहोल्डर अधिक उपयुक्त होगा। हां, आप इसे अपने मॉडल में संभाल सकते हैं लेकिन एक पुरानी छवि को छोड़ने का व्यवहार है, मुझे लगता है, एक त्रुटि प्रदर्शित करने की तुलना में अधिक गलत है।
जेसन गोएमाट

@JasonGoemaat, मैं टूटी हुई छवि को पाठ के साथ बदलने के लिए कैसे करूंगा?
simeg

48

पार्टी के लिए थोड़ा देर से, हालांकि मैं एक प्रणाली में एक ही मुद्दे के कम या ज्यादा हल के साथ आया हूं।

हालाँकि, मेरा विचार imgविश्व स्तर पर हर छवि टैग को संभालने का था ।

मैं अपने HTMLअनावश्यक निर्देशों के साथ काली मिर्च नहीं रखना चाहता था , जैसे err-srcकि यहां दिखाए गए हैं। अक्सर, विशेष रूप से गतिशील छवियों के साथ, आपको पता नहीं चलेगा कि क्या यह बहुत देर तक गायब है। ऑफ-मौके पर अतिरिक्त निर्देश जोड़ने से एक छवि गुम हो जाती है, मुझे लगता है कि यह ओवरकिल है।

इसके बजाय, मैं मौजूदा imgटैग का विस्तार करता हूं - जो, वास्तव में, कोणीय निर्देशों के बारे में क्या है।

तो यही वह है मुझे जो मिला है।

नोट : इसके लिए पूर्ण JQuery लाइब्रेरी मौजूद होना चाहिए और केवल JQlite कोणीय जहाजों के साथ नहीं क्योंकि हम उपयोग कर रहे हैं.error()

आप इसे इस प्लंकर पर कार्रवाई में देख सकते हैं

निर्देश इस तरह बहुत सुंदर लग रहा है:

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

जब कोई त्रुटि होती है (जो कि होगी क्योंकि छवि मौजूद नहीं है या पहुंच से बाहर है) तो हम पकड़ते हैं और प्रतिक्रिया करते हैं। आप छवि आकारों को भी प्राप्त करने का प्रयास कर सकते हैं - यदि वे पहले स्थान पर छवि / शैली में मौजूद थे। यदि नहीं, तो अपने आप को एक डिफ़ॉल्ट सेट करें।

यह उदाहरण छवि के बजाय प्लेसहोल्ड का उपयोग कर रहा है।

अब सभी की छवि, उपयोग की परवाह किए बिना srcया ng-srcखुद को कवर किया है मामले में कुछ भी नहीं लोड ...


2
बहुत अच्छा समाधान! चलो यह एक शीर्ष करने के लिए वोट!
मत्तीज

1
यह कहना काफी सुंदर है। मैं वास्तव में किसी भी छवि को दिखाने के लिए नहीं चाहता हूं अगर यह हल नहीं होता है तो मैंने उपयोग किया: एलिमेंट। एसकेएस ("डिस्प्ले", "कोई नहीं"); बस यह पूरी तरह से छिपाने के लिए
पोम्पी

1
अच्छा :) या आप इसे DOM से पूरी तरह हटा सकते हैं, element.remove () के साथ; :)
डैरेन वेनराइट

महान काम करता है, धन्यवाद!
इकोवो

अपने समाधान को थोड़ा संपादित किया, इसलिए यह तब भी काम करता है जब पथ खाली हो। stackoverflow.com/a/35884288/2014288
andrfas

21

एक लोडिंग त्रुटि या एक खाली स्रोत स्ट्रिंग के दोनों मामलों को पकड़ने के लिए जेसन समाधान का विस्तार करने के लिए, हम सिर्फ एक घड़ी जोड़ सकते हैं।

एचटीएमएल:

<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 string) के साथ आसानी से जाँच की जा सकने वाली घड़ी जोड़ने के लिए एक ओवरकिल लगता है
alonisser

लगता है कि आप बस अपने निर्देश के साथ ngSrc बदल सकते हैं और यह त्रुटि पर बाइंड को सेट करने के लिए इरेज़्स्क का उपयोग करने के बजाय एक अलग इरेज़्स्क निर्देश है, यदि आप चाहते हैं। आप उपयोग कर सकते हैं attrs.$observe('ngSrc', function(value) {...});, कि क्या ngSrc $ घड़ी के बजाय आंतरिक रूप से उपयोग करता है
जेसन Goemaat

रिक्त के साथ पूरी समस्या है क्योंकि ngSrc मूल्य को खाली करने पर src विशेषता को अपडेट नहीं करता है, इसलिए यदि आपके पास ngSrc के स्थान पर अपना स्वयं का निर्देश है तो उसे खाली चेक की आवश्यकता नहीं होगी।
जेसन गोएमाट

1
@Pokono - आप त्रुटि फ़ंक्शन के अंदर देख सकते हैं कि क्या वर्तमान 'src' विशेषता 'इरसेस्क' के समान है।
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 का उपयोग नहीं करता है और समस्या को हल करता है
ग्रेगरा

10

यदि छवि 404 है या छवि शून्य खाली है, तो निर्देश की कोई आवश्यकता नहीं है आप बस इस तरह एनजी-एसकेटी फिल्टर का उपयोग कर सकते हैं :)

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

2
नहीं, यदि p.image एक AJAX कॉल पर 404 लौटाता है, तो वह इसे 'सत्य' मान लेगा और दूसरे img / no-image.png पर नहीं जाएगा।
जेम्स जेंट्स 20

2
@JamesGentes - ऐसा नहीं लगता है। एनजी- src का यह उपयोग मेरे लिए बिल्कुल वैसा ही काम करता है जैसा कि दिखाया गया है। और यह बहुत सरल है।
शन्मेग्रे

@ धन्यवाद धन्यवाद, यह दिलचस्प है - मुझे आश्चर्य है कि अगर पीछे का अंत अलग है। मैं एक्सप्रेस के साथ नोड चला रहा हूं, शायद यह इसे अलग तरीके से संभालता है।
जेम्स जेंटेस

2
@JamesGentes - मेरी पिछली टिप्पणी का सुधार। ओपी एक समाधान की तलाश कर रहा है जब मॉडल द्वारा लौटाए गए वैध यूआरआई है, लेकिन जब इसका पालन किया जाता है तो 404। उस स्थिति में, यह समाधान काम नहीं करता है, इसका परिणाम टूटी हुई छवि में होता है। यदि कोणीय छवि मान के लिए कुछ भी नहीं देता है, तो यह सही ढंग से कमबैक चुनता है।
शन्मेग्रे

लारवेल का उपयोग कर Im और यह मेरे लिए एकदम सही काम करता है अगर 404, अशक्त या खाली है। लेकिन हो सकता है एक्सप्रेस 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
यह सही है, क्योंकि यह "team.logo" को एक स्ट्रिंग (सही / गलत) के रूप में मूल्यांकित करता है, जबकि ng-src {{team.logo}} को तब भी सत्य के रूप में देखेगा जब वह 404 लौटाता है।
जेम्स जेंट्स

2

आपको उसके लिए कोणीय, या यहाँ तक कि CSS या JS की आवश्यकता नहीं है। यदि आप चाहते हैं, तो आप इस उत्तर (जुड़े) को एक सरल निर्देश में लपेट सकते हैं, इसे सरल, पसंद या कुछ बनाने के लिए, लेकिन यह एक बहुत ही सरल प्रक्रिया है ... बस इसे एक ऑब्जेक्ट टैग में लपेटें ...

केवल CSS / HTML (js के बिना) का उपयोग करके इमेज टूटे हुए आइकन को कैसे छिपाएं


1

क्या कोई विशिष्ट कारण है जो आप अपने कोड में फ़ॉलबैक छवि की घोषणा नहीं कर सकते?

जैसा कि मैं समझता हूं, आपके पास अपने छवि स्रोत के लिए दो संभावित मामले हैं:

  1. सही ढंग से जानकारी के टुकड़े सेट करें <4 = फ़ॉलबैक छवि।
  2. सही तरीके से जानकारी के टुकड़े == 4 = उत्पन्न URL।

मुझे लगता है कि इसे आपके ऐप द्वारा नियंत्रित किया जाना चाहिए - यदि वर्तमान में सही URL निर्धारित नहीं किया जा सकता है, इसके बजाय लोडिंग / फ़ॉलबैक / प्लेसहोल्डर छवि URL पास करें।

तर्क यह है कि आपके पास कभी भी एक 'लापता' छवि नहीं है, क्योंकि आपने स्पष्ट रूप से किसी भी समय प्रदर्शित करने के लिए सही URL घोषित किया है।


क्षमा करें, मुझे स्पष्ट करना चाहिए कि भले ही सभी 4 मान सेट हैं, फिर भी URL 404 हो सकता है (उपयोगकर्ता रास्ते में जोड़ सकता है।) इस बीच मैंने एक फ़ंक्शन जोड़ा है जो सभी मानों पर URL की प्रतिक्रिया हेडर की जांच करता है। तैयार। यह अभी भी विशेष उपचार के बिना इसे संभालना अच्छा होगा, मुझे यकीन है कि मैं इस पर फिर से आऊंगा :)
will_hardin

1
कूल, आपको यह दिखाना चाहिए कि उत्तर के रूप में और भविष्य में खोज करने वाले किसी भी व्यक्ति के लिए इसे स्वीकार किया जाए।
एलेक्स ओसबोर्न

1

मेरा सुझाव है कि यदि आप अपनी समस्या को हल करने के निर्देश के रूप में 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 प्लेसहोल्डर छवि के लिए पथ है, या बस एक का उपयोग करेंsrc सामान्य ol 'HTML के अनुसार टैग का ।

जैसे। <img ui-if="!showImage" src="images/placeholder.jpg" />

स्पष्ट रूप से, उपरोक्त सभी कोड नमूने मान रहे हैं कि प्रत्येक मान 1, मान 2, मान 3 और मान 4 आपकी null/ के बराबर होगा falseजब आपकी प्रत्येक 4 जानकारी अधूरी हो (और इस तरह से बूलियन मान भीtrue जब वे पूर्ण होते हैं तो )।

पुनश्च। AngularUI परियोजना को हाल ही में उप-परियोजनाओं में तोड़ दिया गया है, और प्रलेखन के लिए ui-ifवर्तमान में गायब प्रतीत होता है (यह शायद कहीं पैकेज में है)। हालाँकि, जैसा कि आप देख सकते हैं, यह उपयोग करने के लिए बहुत सरल है, और मैंने इसे टीम के लिए इंगित करने के लिए कोणीय UI प्रोजेक्ट पर एक Github 'मुद्दा' भी लॉग इन किया है।

अद्यतन: '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 देता है।

(@ डारेन समाधान का कांटा)

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

यह केवल दो बार लूप की अनुमति देगा, यह जांचने के लिए कि एनजी-एसकेटी मौजूद नहीं है या इरेट-एसकेसी का उपयोग नहीं करता है, यह लूपिंग को रोकता है।

(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);
                }              
            });
            }
        }
    }
})();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.