I have been using Angularjs for a while now, and have encountered an odd problem.
Im rendering returned data into an ng-repeat
i'm able to list the data ordered by the items _id 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 to the bottom of the list (when its needed to be at the top) This was no big deal as I just created an orderBy filter:
data-ng-repeat="post in posts | orderBy:'_id':true"
This did the trick, when a new item is added bingo it is effectively prepended to the ng-repeat list. But (heres the tricky part) each item including the newly added item has the ability to be edited and deleted. This is done by the following:
// 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 does in-fact remove the item from the database, but within the ng-repeat list it removes the item below the desired item to be deleted. Has anyone experience this issue before? Or possible work arounds?
Could this be something to do with track by
?
Also a side note that if i completely remove the orderBy
filter the delete and edit works effectively. But then i'm back where i started, and that being a newly added item appends to the bottom and not the top.
The reason is because $scope.posts
has the items with original order when compared to ng-repeated item with orderBy. Orderby filter rearranges the item, returns a new array and repeats on it instead of the original $scope.posts
array. So the index will be different if the original order is different from the sorted order.
And i believe you are just overdoing stuff, just pass the object as is and get its index for splicing from the original list.
just pass post 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>