来自控制器的AngularJS访问元素嵌套的ng-repeat

时间:2015-07-18 15:10:03

标签: javascript angularjs

我是AngularJS世界的新手,我遇到了一个我无法解决的问题。 我有一个嵌套的ng-repeat视图,因为我有一个嵌套的注释系统,所以我从一个像这样的对象构建视图:

comments: [{
  _id: ObjectId(x),
  parent_id: ObjectId(y),
  text: 'Hello World!',
  author: {
    id: 1,
    name: Jorge
  }
  replies: [{
    _id: ...,
    parent_id: ...
    author: {
      [...]
    }
    replies: [{
      [...]
    }]
  },
  {
    [...]
  }]
}]

因此,每个评论都有一个名为hearts的属性,它是它拥有的喜欢的数量。 我已经实现了socket.io,所以这些都是实时运行的。在我的控制器中,我有一个喜欢评论的新听众,问题是,我如何从我的控制器访问特定评论以更新它?

我已尝试在视图中生成动态ID,例如ng-attr-id="{{'hearts_' + comment._id}}",但这只适用于父母的评论,而不是回复,我不知道为什么。

我还试图生成一个查找注释并更新它的函数,例如这个函数:

    var setNewHearts = function(comments, comment) {
      for (var i = 0; i < comments.length; i++) {
        if ((String(comments[i]._id)) == (String(comment._id))) {
          comments[i].hearts = eventData.comment.hearts;
          return comments;
        } else if (comments[i].replies) {
          setNewHearts(comments[i].replies, eventData.comment);
        } else {
          //$scope.showMoreComments = true;
        }
      }
    }
    console.log(eventData.comment);
    $scope.comments = setNewHearts($scope.comments, eventData.comment);

但是使用这个函数我的$ scope不会实时更新,因为我没有路径去做,我的意思是例如$scope.comments[2].replies[0].replies[3].replies[1]

我希望有人可以帮助我,因为我疯了!我读过一些关于指令的内容。这可能是我的解决方案吗?

非常感谢。

1 个答案:

答案 0 :(得分:2)

递归指令最有意义,但Angular会导致带有递归指令的无限循环,并且解决方法有点难看。您可以递归使用ng-include,如下所示:Live demo (click).

<div ng-repeat="comment in comments" ng-include="'comment.html'"></div>

<script type="text/ng-template"  id="comment.html">
  <div>
    <p>{{comment.author.name}}: {{comment.text}}</p>
    <div class="reply" ng-repeat="comment in comment.replies" ng-include="'comment.html'"></div>
  </div>
</script>

这是我使用的样本数据:

  $scope.comments = [
    {
      id: 1,
      text: 'Hello World!',
      author: {
        id: 1,
        name: 'Jorge'
      },
      replies: [
        {
          id: 2,
          text: 'Hey, Jorge!',
          author: {
            id: 2,
            name: 'World'
          },
          replies: [
            {
              id: 3,
              text: 'Woah!',
              author: {
                id: 1,
                name: 'Jorge'
              }
            }
          ]
        }
      ]
    }
  ];

对于套接字消息进入时的更新,我会这样做:

socket.on('comment-liked', function(commentId) {
  $scope.$apply(function() {
    // recursively search all objects and return object where `obj.id === commentId`
    var comment = findCommentById($scope.comments, likedCommentId);
    // increment the counter or set to 1 if there were no hearts before
    comment.hearts = comments.hearts ? ++comment.hearts : 1;
  });
});

这是我获取一系列匹配注释的函数。它使用lodash /下划线flatten,但如果你愿意,你可以很容易地手动完成。最好是使用npm模块,这样你就可以很容易地包含lodash的flatten,而不需要用整个库扩展你的代码= D

function findCommentById(comments, id) {
  return _.flatten(comments.map(function(comment) {
    if (comment.id === id) { return comment; }
    return findCommentById(comment.replies, id);
  }))[0];
}

正如您在this demo中所看到的,评论会根据您的意愿进行更新。