如果src错误,angular-splice数组内部指令

时间:2015-10-31 12:44:27

标签: javascript angularjs

如果图像不存在,我需要删除项目并在ng-repeat内推送下一步。

目前我正在使用next指令

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(),则不会将下一个项目推送到数组。

这是fiddle

另一个想法是在控制器中编写函数,然后从指令运行它:

$scope.splicePost = (post) =>
  $scope.posts.splice( $scope.posts.indexOf(post), 1 )

我无法理解如何做到的问题。也许需要使用隔离范围?

3 个答案:

答案 0 :(得分:2)

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

由于事件在angular core之外,因此当更改范围并使用$apply$timeout

完成此操作时,您需要告诉angular运行摘要。

为了使它更具可重用性,最好创建隔离范围并传入post项并将数组发布到隔离范围

DEMO

答案 1 :(得分:0)

是的,你是正确的,你需要将数组传递给指令,如果图像无法加载,你可以从数组中拼接。使用' ='将其传递到隔离范围内,这样就可以进行双向绑定。

如果发生错误,则拼接,否则不执行任何操作。

更新: 代码:

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>

答案 2 :(得分:0)

我更愿意在组件中思考,这意味着您可以创建一个名为image-block的组件,该组件具有您之前在标记中使用的模板。您的标记现在看起来像这样:

<div ng-controller="MyCtrl as vm">
  <image-block images="vm.posts" url-property="image_url"></image-block>
</div>

您传入imagesurlProperty,组件可以在其下找到每个图片的网址。 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函数。

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

唯一的范围属性是图像,它将被传递到父控制器以从列表中删除图像。

以下是JSFiddle的更新版本。就个人而言,我发现组件中的思维方式非常有用,它有助于将逻辑和UI细分为更小的部分。