AngularJS new push () 'ed item to ngRepeat $ Scope does not edit or delete effectively

I have been using Angularjs for a while and am facing an odd problem.

Im rendering the returned data in ng-repeat

, I can list the data ordered by _id elements, thus showing the newest first. But when I created an add function that inserts a new item and uses push

, the subsequent item was added at the bottom of the list (when it needed to be at the top). It didn't matter as I just created the orderBy filter

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

      

This did the trick, when a new item is added to bingo, it is actually added to the ng-repeat list. But (this is the tricky part) every element, including the newly added element, can be edited and removed. This is done as follows:

// 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);
    })
}

      

The above actually removes the item from the database, but in the ng-repeat list, it removes the item under the desired item to be removed. Has anyone experienced this problem before? Or is it possible to work around?

Could this be related to track by

?

Also note that if I remove the filter completely orderBy

, deleting and editing works effectively. But then I went back to where I started, and that the added item is being added to the bottom, not the top.

+3


source to share


2 answers


The reason is because it $scope.posts

has elements with original order versus ng-repeated element with orderBy. The Orderby filter reorders the element, returns a new array, and iterates over the original array $scope.posts

. Thus, the index will be different if the original order is different from the ordered order.

And I believe you are just overdoing it, just pass the object as is and get its index to be spliced โ€‹โ€‹from the original list.

just send a message from ng-click:

ng-click="deletePost(post)" 

      



and in the controller:

$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>
      

Run codeHide result


+3


source


Do not delete the item by index, perhaps your $ scope.posts order and the order you made do not match. When u is using orderBy filter ng-repeat, create a new array to render, don't reorder $ scope.posts.

You can remove an item by its ID. it is more secure.



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

      

Also if you want to show the inserted row first, you should use instead of push

+1


source







All Articles