[英]angular - splice array inside directive if src error
I need to remove item and push next inside ng-repeat if image is not exist. 如果图像不存在,我需要删除项目并在ng-repeat中推送下一个。
Currently i using next directive 目前我正在使用下一条指令
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();
});
}
};
});
Obviously if use element.parent().remove()
or splice()
it does not push next item to array. 显然,如果使用
element.parent().remove()
或splice()
,则不会将下一项推入数组。
As another idea is write function in controller and then run it from directive: 另一个想法是在控制器中写入函数,然后从指令运行它:
$scope.splicePost = (post) =>
$scope.posts.splice( $scope.posts.indexOf(post), 1 )
The problem that i can't get how to do that. 我无法做到这一点的问题。 Maybe need to use isolate scope?
也许需要使用隔离范围?
ng-repeat
creates a child scope for each item in the repeater. ng-repeat
为转发器中的每个项目创建一个子范围。
This means that inside the directive you will inherit the parent scope array as well as have access to scope.post
for each post item. 这意味着在指令内,您将继承父作用域数组,并可以访问每个发布项目的
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);
});
});
}
};
});
Since the event is outside of angular core you need to tell angular to run a digest when the scope is changed and this is done using $apply
or $timeout
由于该事件不在angular核心之外,因此您需要告诉angular在更改范围时运行摘要,这可以使用
$apply
或$timeout
To make this more re-useable it would be better to create isolated scope and pass in the post item and post array to the isolated scope 为了使其更可重用,最好创建隔离的作用域并将post项目和post数组传递给隔离的作用域
Yes you are correct, you will need to pass the array into the directive, and if the image cannot load, you can splice from the array. 是的,您是正确的,您需要将数组传递到指令中,如果无法加载映像,则可以从数组中进行拼接。 pass it in isolated scope with '=', so you have two way binding.
用'='在孤立的范围内传递它,所以您有两种方式绑定。
If an error happens, splice, otherwise, do nothing. 如果发生错误,请进行拼接,否则,什么也不做。
UPDATE: Code: 更新:代码:
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();
});
}
};
});
The html will become: 该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>
I would rather think in components, means you could create a component called image-block
which has the template you used in your markup before. 我宁愿想到组件,这意味着您可以创建一个名为
image-block
组件,该组件具有之前在标记中使用的模板。 Your markup now could look like this: 您的标记现在可能如下所示:
<div ng-controller="MyCtrl as vm">
<image-block images="vm.posts" url-property="image_url"></image-block>
</div>
You pass in the images
and the urlProperty
under which the component can find the url for each image. 您传入
images
和urlProperty
在该urlProperty
下组件可以找到每个图像的url。 The image-block
directive is implemented as follows: 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);
}
};
}]
};
});
The component has its own controller for logic, which also gets required by the isImage
directive. 该组件具有自己的逻辑控制器,
isImage
指令也需要该isImage
。 This directive will catch the error
event and calls the removeImage
function of the parent controller. 该指令将捕获
error
事件并调用父控制器的removeImage
函数。
The isImage
directive looks like this: 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));
});
}
};
});
The only scope property is the image, which will be passed along to the parent controller to remove the image from the list. 唯一的scope属性是图像,它将被传递到父控制器以从列表中删除图像。
Here is an updated version of your JSFiddle . 这是JSFiddle的更新版本。 Personally I find the way of thinking in components very useful and it helps to break down your logic and UI into smaller pieces.
我个人认为组件的思维方式非常有用,它有助于将逻辑和UI分解为更小的部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.