Мне нужно удалить элемент и нажать дальше внутри ng-repeat, если изображение не существует.
В настоящее время я использую следующую директиву
myApp.directive("noImage", function() {
return {
link: function(scope, element, attrs) {
return element.bind("error", function() {
element.attr("src", attrs.noImage);
return element.addClass('no-img');
//return element.parent().remove();
//return element.parent().splice();
});
}
};
});
Очевидно, что если использовать element.parent().remove()
или splice()
он не перетаскивает следующий элемент в массив.
Вот скрипка
Еще одна идея - это функция записи в контроллере, а затем запустить ее из директивы:
$scope.splicePost = (post) =>
$scope.posts.splice( $scope.posts.indexOf(post), 1 )
Проблема в том, что я не могу понять, как это сделать. Может быть, нужно использовать изоляцию?
ng-repeat
создает дочернюю область для каждого элемента репитера.
Это означает, что внутри директивы вы наследуете массив родительских областей, а также имеете доступ к scope.post
для каждого элемента сообщения.
myApp.directive("noImage", function () {
return {
link: function (scope, element, attrs) {
element.bind("error", function () {
// get index of post in the posts array
var idx = scope.posts.indexOf(scope.post);
scope.$apply(function () {
// splice posts array
scope.posts.splice(idx, 1);
});
});
}
};
});
Поскольку событие находится за пределами углового ядра, вам нужно указать угловое значение, чтобы запустить дайджест, когда область изменена, и это делается с использованием $apply
или $timeout
Чтобы сделать это более пригодным для повторного использования, было бы лучше создать изолированную область и передать в столбце post и post array в изолированную область
Да, вы правы, вам нужно передать массив в директиву, и если изображение не может загрузить, вы можете сращиться с массивом. передайте его в изолированном объеме с помощью "=", поэтому у вас есть двусторонняя привязка.
Если произошла ошибка, сращивание, в противном случае, ничего не делать.
ОБНОВЛЕНИЕ: Код:
var myApp = angular.module('myApp',[]);
myApp.directive("noImage", function() {
return {
scope: {
posts: "="
},
link: function(scope, element, attrs) {
return element.bind("error", function() {
scope.posts.splice(scope.$parent.$index, 1);
scope.$apply();
});
}
};
});
Html станет:
<div ng-controller="MyCtrl">
<ul>
<li ng-repeat = 'post in posts | limitTo: 5'>
<img posts="posts" ng-src = "{{post.image_url}}" no-image = "" />
</li>
</ul>
</div>
Я бы предпочел подумать о компонентах, значит, вы могли бы создать компонент, называемый image-block
который ранее использовал шаблон, используемый в вашей разметке. Теперь ваша разметка может выглядеть так:
<div ng-controller="MyCtrl as vm">
<image-block images="vm.posts" url-property="image_url"></image-block>
</div>
Вы передаете images
и urlProperty
под которыми компонент может найти URL для каждого изображения. Директива image-block
изображения реализуется следующим образом:
myApp.directive("imageBlock", function() {
return {
restrict: 'E',
scope: {
images: '=',
urlProperty: '@',
limit: '@'
},
template:
'<ul>' +
'<li ng-repeat="image in images | limitTo: limit || 3">' +
'<img ng-src="{{ image[urlProperty] }}" is-image="image" />' +
'</li>' +
'</ul>',
controller: ['$scope', function(scope) {
this.removeImage = function(image) {
var index = scope.images.indexOf(image);
if(index > 0) {
scope.images.splice(index, 1);
}
};
}]
};
});
Компонент имеет свой собственный логический контроллер, который также требуется директивой isImage
. Эта директива поймает событие error
и removeImage
функцию removeImage
родительского контроллера.
Директива isImage
выглядит так:
myApp.directive("isImage", function() {
return {
scope: {
image: '=isImage'
},
require: '^imageBlock',
link: function(scope, element, attrs, ctrl) {
return element.bind("error", function() {
scope.$apply(ctrl.removeImage(scope.image));
});
}
};
});
Единственным свойством scope является изображение, которое будет передано вместе с родительским контроллером для удаления изображения из списка.
Вот обновленная версия вашего JSFiddle. Лично я считаю, что способ мышления в компонентах очень полезен, и помогает разбить вашу логику и интерфейс на более мелкие части.