Если путь ngSrc разрешается до 404, существует ли способ отступить к умолчанию?

Приложение, которое я создаю, требует, чтобы мой пользователь установил 4 части информации, прежде чем этот образ даже получит возможность загрузки. Это изображение является центральным элементом приложения, поэтому сломанная ссылка на изображение делает его похожим на все, что угодно. Я хотел бы, чтобы другое изображение заняло свое место на 404.

Любые идеи? Я хотел бы избежать написания пользовательской директивы для этого.

Я был удивлен, что я не мог найти аналогичный вопрос, особенно когда первый вопрос в документах является одним и тем же!

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

Ответ 1

Это довольно простая директива для просмотра ошибки загрузки изображения и замены 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);
        }
      });
    }
  }
});

Если вы хотите отобразить изображение ошибки, когда ngSrc пуст, вы можете добавить этот (Plunker):

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

Проблема заключается в том, что ngSrc не обновляет атрибут src, если значение пустое.

Ответ 2

Немного поздно вечеринке, хотя я придумал решение более или менее той же проблемы в системе, которую я создаю.

Моя идея заключалась, однако, в том, чтобы обрабатывать EVERY image img тег глобально.

Мне не нужно было перенести мои HTML с помощью ненужных директив, таких как показанные здесь err-src. Довольно часто, особенно с динамическими изображениями, вы не будете знать, хватит ли его, пока не станет слишком поздно. Добавление дополнительных директив на случайный шанс отсутствует, кажется, излишним для меня.

Вместо этого я расширяю существующий тег img, который действительно является директивой Angular.

Итак - вот что я придумал.

Примечание. Для этого требуется наличие полной библиотеки JQuery, а не только JQlite Angular, потому что мы используем .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, сам покрыт, если ничего не загружается...

Ответ 3

Чтобы расширить решение Jason, чтобы уловить оба случая ошибки загрузки или пустую строку источника, мы можем просто добавить часы.

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

    }
  }
});

Ответ 4

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

Ответ 5

Если изображение равно 404, или изображение пустым, все, что не требуется директивам, вы можете просто использовать фильтр ng-src следующим образом:)

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

Ответ 6

Я использую что-то вроде этого, но он предполагает, что команда .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">

Ответ 7

Для этого вам не нужен angular или даже CSS или JS. Если вы хотите, вы можете обернуть этот ответ (связанный) в простой директиве, чтобы сделать его проще, например или что-то, но это довольно простой процесс... просто оберните его в тег объекта...

Как скрыть изображение сломанной Icon, используя только CSS/HTML (без js)

Ответ 8

Есть ли конкретная причина, по которой вы не можете объявить резервное изображение в своем коде?

Как я понимаю, у вас есть два возможных случая для вашего источника изображения:

  • Правильно установить фрагменты информации < 4 = Обратное изображение.
  • Правильно установить фрагменты информации == 4 = Сгенерированный URL.

Я думаю, что это должно быть обработано вашим приложением - если правильный URL-адрес в настоящее время не может быть определен, вместо этого передайте URL-адрес загружаемого/резервного/placeholder-изображения.

Мысль о том, что у вас никогда не было "отсутствующего" изображения, потому что вы явно указали правильный URL-адрес для отображения в любой момент времени.

Ответ 9

Я предлагаю вам использовать директиву Angular UI Utils 'if statement' для решения вашей проблемы, как показано на 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:

Код контроллера:

$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, value2, value3 и value4 будет равен null/false, когда каждый из ваших 4 частей информации будет неполным (и, следовательно, также булевым значение true, когда они завершены).

PS. Недавно проект AngularUI был разбит на подпроекты, и в настоящее время отсутствует документация для ui-if (вероятно, в пакете есть). Тем не менее, это довольно просто использовать, как вы можете видеть, и я зарегистрировал проблему Github в проекте Angular UI, чтобы указать его команде.

UPDATE: "ui-if" отсутствует в проекте AngularUI, потому что он интегрирован в основной код AngularJS! Только с v1.1.x, хотя в настоящее время он помечен как "нестабильный".

Ответ 10

Вот решение, которое я придумал, используя собственный javascript. Я проверяю, если изображение сломано, а затем добавьте класс к изображению на всякий случай и изменив исходный код.

Я получил часть ответа из ответа 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';
            };
        }
    }
});

Ответ 11

Придумал мое собственное решение. Он заменяет изображение, если src или ngSrc пуст, и если img возвращает 404.

(fork решения @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);
        }
    }
}
});

Ответ 12

Это позволит только дважды зацикливать, чтобы проверить, не существует ли ng-src else, использовать 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);
                }              
            });
            }
        }
    }
})();