繁体   English   中英

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

[英]angular - splice array inside directive if src error

如果图像不存在,我需要删除项目并在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);
                });
            });
        }
    };
});

由于该事件不在angular核心之外,因此您需要告诉angular在更改范围时运行摘要,这可以使用$apply$timeout

为了使其更可重用,最好创建隔离的作用域并将post项目和post数组传递给隔离的作用域

演示

是的,您是正确的,您需要将数组传递到指令中,如果无法加载映像,则可以从数组中进行拼接。 用'='在孤立的范围内传递它,所以您有两种方式绑定。

如果发生错误,请进行拼接,否则,什么也不做。

更新:代码:

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>

您传入imagesurlProperty在该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指令也需要该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));
      });
    }
  };
});

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

这是JSFiddle的更新版本。 我个人认为组件的思维方式非常有用,它有助于将逻辑和UI分解为更小的部分。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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