AngularJS 新推送 () 到 ngRepeat $Scope 的项目没有有效地编辑或删除

AngularJS newly push()'ed item to ngRepeat $Scope doesn't edit or delete effectively

我使用 Angularjs 有一段时间了,遇到了一个奇怪的问题。

我将返回的数据渲染到 ng-repeat 我能够列出按项目 _id 排序的数据,从而首先显示最新的。但是当我创建一个插入新项目并使用 push 的添加函数时,后续项目被添加到列表的底部(当它需要位于顶部时)这没什么大不了的,因为我刚刚创建了一个按过滤器排序:

data-ng-repeat="post in posts | orderBy:'_id':true"

这成功了,当一个新项目被添加到 bingo 时,它被有效地添加到 ng-repeat 列表中。但是(这里是棘手的部分)包括新添加的项目在内的每个项目都可以编辑和删除。这是通过以下方式完成的:

// within ng-repeat
ng-click="deletePost($index,post._id)" 

// Subséquent function
$scope.deletePost = function(idx, id) {
    // Delete Post
    Blog.Post.delete({ id:id }, function(success) {
        $scope.posts.splice(idx, 1);
    })
}

以上实际上确实从数据库中删除了该项目,但在 ng-repeat 列表中,它删除了要删除的所需项目下方的项目。有没有人遇到过这个问题?或者可能的解决方法?

这可能与 track by 有关吗?

另外请注意,如果我完全删除 orderBy 过滤器,则删除和编辑会有效。但后来我又回到了开始的地方,作为新添加的项目附加到底部而不是顶部。

不要按索引删除项目,也许您的 $scope.posts 订单和呈现的订单不一样。当您使用 orderBy 过滤器 ng-repeat 为渲染创建新数组时,不要重新排序 $scope.posts.

您可以通过 ID 删除项目。更安全。

var index;
$filter($scope.posts, function(val, key){
    if(val._id === id && !index)
        index = key;
})
if(index){
    $scope.posts.splice(index, 1);
}

此外,如果你想首先显示插入的行,你应该使用 unshift instead of push

原因是因为 $scope.posts 与具有 orderBy 的 ng-repeated 项目相比,具有原始订单的项目。 Orderby 过滤器重新排列项目,returns 一个新数组并在其上重复而不是原始 $scope.posts 数组。因此,如果原始顺序与排序顺序不同,索引将不同。

而且我认为你只是做得太过了,只需按原样传递对象并从原始列表中获取其拼接索引。

只需从 ng-click 传递 post:

ng-click="deletePost(post)" 

在控制器中:

$scope.deletePost = function(post) { //Get post object
    var posts = $scope.posts;
    /*Delete with the _id property*/
    Blog.Post.delete({ id:post._id }, function(success) {
        /*Get the original index with the object reference and splice it*/
        posts.splice(posts.indexOf(post), 1);
    });
}

angular.module('app', []).controller('ctrl', function($scope) {
  $scope.posts = [{
    _id: 'id1',
    name: 'Post1'
  }, {
    _id: 'id2',
    name: 'Post2'
  }, {
    _id: 'id3',
    name: 'Post3'
  }, {
    _id: 'id4',
    name: 'Post4'
  }]
  $scope.deletePost = function(post) {
    var posts = $scope.posts;
    posts.splice(posts.indexOf(post), 1);
  }
  $scope.addPost = function() {
    var posts = $scope.posts;
    posts.push({
      _id: 'id' + (posts.length + 1),
      name: 'Post' + (posts.length + 1)
    });
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <button ng-click="addPost()">Add</button>
  <div data-ng-repeat="post in posts | orderBy:'_id':true">
    <div ng-click="deletePost(post)">{{post.name}}</div>
  </div>
</div>