【问题标题】:angular - splice array inside directive if src error角度 - 如果 src 错误,则在指令内拼接数组
【发布时间】:2015-10-31 21:33:28
【问题描述】:

如果图像不存在,我需要删除项目并在 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(),它不会将下一项推送到数组中。

这里是fiddle

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

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

我无法做到这一点的问题。也许需要使用隔离范围?

【问题讨论】:

    标签: javascript angularjs


    【解决方案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 完成的

    为了使其更可重用,最好创建隔离范围并将帖子项和帖子数组传递给隔离范围

    DEMO

    【讨论】:

    【解决方案2】:

    是的,您是正确的,您需要将数组传递给指令,如果图像无法加载,您可以从数组中拼接。使用 '=' 在隔离范围内传递它,因此您有两种方式绑定。

    如果发生错误,拼接,否则,什么都不做。

    更新: 代码:

    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>
    

    【讨论】:

      【解决方案3】:

      我宁愿在组件中思考,这意味着您可以创建一个名为 image-block 的组件,其中包含您之前在标记中使用的模板。您的标记现在可能如下所示:

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

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

      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 分解成更小的部分。

      【讨论】:

        猜你喜欢
        • 2017-12-04
        • 1970-01-01
        • 1970-01-01
        • 2015-03-15
        • 1970-01-01
        • 1970-01-01
        • 2018-08-14
        • 2017-04-01
        • 1970-01-01
        相关资源
        最近更新 更多