angularjs - img - ngsrc angular5
si una ruta ngSrc se resuelve en 404, ¿hay alguna manera de volver a un valor predeterminado? (12)
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.
¿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:
- Piezas de información correctas <4 = Imagen de respaldo.
- 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.
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);
}
}
}
});
Es una directiva bastante simple observar un error al cargar una imagen y reemplazar el 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);
}
});
}
}
});
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.
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);
}
});
}
}
}
})();
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)
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:
<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);
}
}
});
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 :)
<img ng-src="{{ p.image || ''img/no-image.png'' }}" />
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: <img ui-if="showImage()" ng-src="images/{{data.value}}.jpg" />
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: <img ui-if="showImage" ng-src="images/{{data.value}}.jpg" />
Para una imagen de marcador de posición, simplemente agregue otra etiqueta <img>
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. <img ui-if="!showImage" src="images/placeholder.jpg" />
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''.
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 etiquetas 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 reaccionamos. 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 ...
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.
<img ng-if="team.logo" ng-src="https://api.example.com/images/{{team.logo}}">
<img ng-hide="team.logo" ng-src="img/default.png">
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:
<img class="img-circle" check-image ng-src="{{item.profileImg}}" />