简体   繁体   English

angular-如果src错误,则在指令内部拼接数组

[英]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() ,则不会将下一项推入数组。

Here is fiddle 这是小提琴

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数组传递给隔离的作用域

DEMO 演示

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. 您传入imagesurlProperty在该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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM