si una ruta ngSrc se resuelve en 404, ¿hay alguna manera de volver a un valor predeterminado?

La aplicación que estoy creando requiere que el usuario establezca 4 elementos de información antes de que esta imagen tenga posibilidad de cargarse. Esta imagen es la pieza central de la aplicación, por lo que el enlace de la imagen rota hace que parezca que todo está borked. Me gustaría que otra imagen ocupe su lugar en un 404.

¿Algunas ideas? Me gustaría evitar escribir una directiva personalizada para esto.

Me sorprendió que no pudiera encontrar una pregunta similar, especialmente cuando la primera pregunta en el documento es la misma.

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

    Es una directiva bastante simple observar un error al cargar una imagen y reemplazar el src. (Plunker)

    Html:

     

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

    Si desea visualizar la imagen de error cuando ngSrc está en blanco, puede agregar esto (Plunker) :

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

    El problema es que ngSrc no actualiza el atributo src si el valor está en blanco.

    Un poco tarde para la fiesta, aunque se me ocurrió una solución para más o menos el mismo problema en un sistema que estoy construyendo.

    Mi idea era, sin embargo, manejar TODAS las tags de img imagen a nivel mundial.

    No quería tener que utilizar mi HTML con directivas innecesarias, como las que se muestran aquí. Muy a menudo, especialmente con imágenes dinámicas, no sabrá si falta hasta que sea demasiado tarde. Agregar directivas adicionales en caso de que falte una imagen me parece exagerada.

    En cambio, extiendo la etiqueta img existente, que, en realidad, es de lo que se tratan las directivas angulares.

    Entonces, esto es lo que se me ocurrió.

    Nota : Esto requiere que la biblioteca JQuery completa esté presente y no solo se envíe el JQlite Angular porque estamos usando .error()

    Puedes verlo en acción en este Plunker

    La directiva se parece mucho a esto:

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

    Cuando ocurre un error (que será debido a que la imagen no existe o es inalcanzable, etc.) capturamos y reactjsmos. Puede intentar obtener los tamaños de imagen también, si estaban presentes en la imagen / estilo en primer lugar. De lo contrario, configúrate un valor predeterminado.

    Este ejemplo usa placehold.it para que se muestre una imagen.

    Ahora, CADA imagen, independientemente de usar src o ng-src ha cubierto en caso de que no se cargue nada ...

    Para expandir la solución de Jason y detectar los casos de error de carga o cadena de fuente vacía, podemos agregar un reloj.

    Html:

      

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

    Si la imagen es 404 o la imagen está vacía, lo que sea que no haya necesidad de instrucciones, simplemente puede usar el filtro ng-src como este 🙂

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

    en HTML:

      

    Uso algo como esto, pero asume que team.logo es válido. Fuerza el valor predeterminado si “team.logo” no está configurado o está vacío.

       

    No necesita angular para eso, ni siquiera CSS o JS. Si lo desea, puede envolver esta respuesta (vinculada) en una directiva simple para que sea más simple, como o algo así, pero es un proceso bastante simple … solo envuélvalo en una etiqueta de objeto …

    Cómo ocultar la imagen del icono roto utilizando solo CSS / HTML (sin js)

    ¿Hay alguna razón específica por la que no puedas declarar la imagen alternativa en tu código?

    Según tengo entendido, tienes dos posibles casos para tu fuente de imagen:

    1. Piezas de información correctas <4 = Imagen de respaldo.
    2. Información correcta configurada == 4 = URL generada.

    Creo que esto debería ser manejado por su aplicación: si actualmente no se puede determinar la URL correcta, pase una URL de imagen de carga / retroceso / marcador de posición.

    El razonamiento es que nunca tiene una imagen “perdida” porque ha declarado explícitamente la URL correcta para mostrar en cualquier momento.

    Sugiero que le gustaría utilizar la directiva ‘if statement’ de Angular UI Utils para resolver su problema, como se encuentra en http://angular-ui.github.io/ . Lo acabo de usar para hacer exactamente lo mismo.

    Esto no se ha probado, pero podrías hacer algo como:

    Código del controlador:

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

    (o más simple)

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

    HTML en la vista:

    O incluso más simple, podrías usar una propiedad de ámbito:

    Código del controlador:

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

    HTML en la vista:

    Para una imagen de marcador de posición, simplemente agregue otra etiqueta similar, anteponga su parámetro ui-if con una marca de exclamación ( ! ) Y haga que ngSrc tenga la ruta a la imagen de marcador de posición, o simplemente use una etiqueta src como ‘HTML.

    p.ej.

    Obviamente, todas las muestras de código anteriores suponen que cada valor1, valor2, valor3 y valor4 equivaldrán a null / false cuando cada una de sus 4 piezas de información esté incompleta (y por lo tanto también a un valor booleano de true cuando estén completas )

    PD. El proyecto AngularUI se ha dividido recientemente en subproyectos, y la documentación para ui-if parece faltar actualmente (aunque probablemente esté en el paquete). Sin embargo, es bastante fácil de usar como puede ver, y he registrado un ‘problema’ de Github en el proyecto de interfaz de usuario angular para señalarlo también al equipo.

    ACTUALIZACIÓN: ‘ui-if’ no se encuentra en el proyecto AngularUI porque se ha integrado en el código AngularJS básico. Solo a partir de v1.1.x, que actualmente está marcado como ‘inestable’.

    Aquí hay una solución que se me ocurrió usando Javascript nativo. Estoy comprobando si la imagen está rota, luego agregué una clase a la imagen por si acaso y cambié la fuente.

    Obtuve una parte de mi respuesta de una respuesta de 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'; }; } } }); 

    Caí con mi propia solución. Reemplaza la imagen tanto si src o ngSrc están vacíos, y si img devuelve 404.

    (tenedor de la solución @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); } } } }); 

    Esto solo permitirá hacer un bucle dos veces, para verificar si el ng-src no existe, use el err-src, esto evita que continúe el bucle.

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