Как показать объект в цикле AngularJS ng-repeat, только если существует его вложенное изображение?
Мой внешний интерфейс, управляемый AngulaJS, получает данные из местного JSON
файл и позже переключится на API. Данные представляют собой список Project
объекты с вложенными списками Image
объекты. Я отображаю эти данные в цикле:
<div id="projects" ng-app="portfolio">
<div id="projectsList" ng-controller="ProjectsListController as projectsList">
<div class="projectItem" ng-repeat="projectItem in projectsList.projectsListData._embedded.projects">
<div class="project-image">
<img
ng-src="{{projectItem._embedded.images[0].src}}"
title="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
alt="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
/>
</div>
</div>
</div>
</div>
Но иногда изображение src
неверно (ошибка 404
). Было бы лучше пропустить такие проекты, где первое изображение (images[0]
) не может быть найден. Как заставить скрипт пропустить нерелевантные объекты?
РЕДАКТИРОВАТЬ
У меня уже есть три ответа, но решения не работают, и я хочу точно объяснить проблему:
src
Свойство изображений всегда установлено. Это не проблема. Это означает, что проверка, установлена ли она или нет (как ng-show="projectItem._embedded.images[0].src != ''"
или же ng-if="{{projectItem._embedded.images[0].src}}"
) не будет работать - не может работать.
Это не работает - src
свойство установлено. Это неправильно (будет 404
ошибка), но она установлена и projectItem._embedded.images[0].src != ''
вернусь true
и для "неактуальных" объектов.
4 ответа
Это хакерский способ сделать эту работу:
Чтобы избежать загрузки изображений, когда они бросают 404
ошибка или когда изображения являются недействительными,
Это должно быть внутри вашего контроллера. Эта функция проверяет, является ли URL-адрес изображения действительным / недействительным.
$scope.imageExists = function(image, object, index) {
var img = new Image();
img.onload = function() {
object[index] = true;
$scope.$apply();
};
img.onerror = function() {
return false;
};
img.src = image;
};
Сейчас на виду:
Я инициирую объект под названием img={};
в ng-repeat
,
Затем инициализация значения для этого индекса в ng-repeat
в $scope.imageExists
функция. Внутри этой функции, при успешной загрузке этого изображения, я устанавливаю img[index]= true
,
<div ng-repeat="image in images" ng-init="img = {}">
<img ng-src="{{image}}" ng-init="img[$index] = imageExists(image, img, $index)" ng-show="img[$index]">
</div>
Таким образом, применяя его к вашему коду:
<div id="projects" ng-app="portfolio">
<div id="projectsList" ng-controller="ProjectsListController as projectsList">
<div class="projectItem" ng-repeat="projectItem in projectsList.projectsListData._embedded.projects" ng-init="img = {}">
<div class="project-image" ng-init="img[$index] = imageExists(projectItem._embedded.images[0].src, img, $index)" ng-show="img[$index]">
<img
ng-src="{{projectItem._embedded.images[0].src}}"
title="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
alt="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
/>
</div>
</div>
</div>
</div>
Поместите $scope.imageExists
код сверху на ваш контроллер.
Вы можете использовать нг-если
<div class="projectItem" ng-repeat="projectItem in projectsList.projectsListData._embedded.projects" ng-if="{{projectItem._embedded.images[0].src}}">
<div class="project-image">
<img
ng-src="{{projectItem._embedded.images[0].src}}"
title="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
alt="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
/>
</div>
</div>
</div>
Или вы также можете использовать ng-show/ng-hide, который просто не показывает элемент, но будет присутствовать в DOM.
Но будьте осторожны при использовании ng-if, поскольку он создает свою собственную область видимости.
РЕДАКТИРОВАТЬ: Если URL-адрес уже установлен, то один из способов - проверить, существует ли URL-адрес с помощью этого метода (или чего-либо подобного). JavaScript/jQuery проверяет битые ссылки ng-if="UrlExists(projectItem._embedded.images[0].src)"
Вы можете создать свою собственную директиву об изображении:
<my-image src="http://someimageurl"></my-image>
Если изображение существует, директива вставит изображение в DOM. Если это не так, то вы можете проигнорировать это или вставить сообщение.
var app = angular.module('app', []);
app.directive('myImage', function() {
return {
restrict: 'E',
replace:true,
link: function(scope, element, attr) {
var image = new Image();
image.onload = function() {
element.append(image);
}
image.onerror = function() {
element.html('Something went wrong or the image does not exist...');
}
image.src = attr.src;
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<my-image src="https://www.google.ca/images/srpr/logo11w.png" />
<my-image src="https://server/images/doesnotexist.png" />
</div>
<div class="project-image" ng-if="projectItem._embedded.images[0].src != ''">
<img
ng-src="{{projectItem._embedded.images[0].src}}"
title="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
alt="{{projectItem.title}} - {{projectItem._embedded.images[0].title}}"
/>
</div>