AngularJS new push()'ed项目到ngRepeat $ Scope不能有效地编辑或删除

时间:2015-01-05 18:42:57

标签: javascript angularjs angularjs-scope angularjs-ng-repeat angularjs-filter

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

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

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过滤器,则删除和编辑会有效。但后来我回到了我开始的地方,并且这是一个新添加的项目附加到底部而不是顶部。

2 个答案:

答案 0 :(得分:3)

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

而且我相信你只是过度使用东西,只需按原样传递对象并从原始列表中获取拼接索引。

只需从ng-click传递帖子:

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>

答案 1 :(得分:1)

不要按索引删除项目,可能是您的$ 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);
}

此外,如果您想首先显示插入的行,则应使用推送

的非强制代替