Angularjs invalid $ index after orderBy

I am new to Angular.js and have some problems sorting my array and working on this sorted data.

I have a list with items and want to sort it by "Store.storeName", which still works. But after sorting the data, my delete function no longer works. I think this is because after sorting, the $ index is incorrect, and therefore the invalid data is deleted.

How can i solve this? Ordering data in an area, not in a view? How to do it?

Here is the code:

In view:

<tr ng-repeat="item in items | orderBy:'Store.storeName'"> <td><input class="toggle" type="checkbox" ng-model="item.Completed"></td> <td>{{item.Name}}</td> <td>{{item.Quantity}} Stk.</td> <td>{{item.Price || 0 | number:2}} €</td> <td>{{item.Quantity*item.Price|| 0 | number:2}} €</td> <td>{{item.Store.storeName}}</td> <td><a><img src="img/delete.png" ng-click="removeItem($index)">{{$index}}</a></td> </tr> 

And in my controller, I have this delete function, which should delete certain data:

 $scope.removeItem = function(index){ $scope.items.splice(index,1); } 

This works well before ordering in view. If something important is missing, let me now.

Thank!

+79
sorting angularjs indexing angularjs-orderby
Apr 20 '13 at 9:32
source share
6 answers

Instead of relaying to $index , which, as you noticed, will point to an index in a sorted / filtered array, you can pass this element directly to your removeItem function:

 <a><img src="img/delete.png" ng-click="removeItem(item)">{{$index}}</a> 

and change the removeItem function to find the index using the indexOf method of the array as follows:

 $scope.removeItem = function(item){ $scope.items.splice($scope.items.indexOf(item),1); } 
+127
Apr 20 '13 at 9:49 on
source share

I had the same problem and other answers in this thread are not suitable for my situation.

I solved the problem with a custom filter:

 angular.module('utils', []).filter('index', function () { return function (array, index) { if (!index) index = 'index'; for (var i = 0; i < array.length; ++i) { array[i][index] = i; } return array; }; }); 

which can be used as follows:

 <tr ng-repeat="item in items | index | orderBy:'Store.storeName'"> 

and then in HTML you can use item.index instead of $index .

This method is suitable for collections of objects.

Please note that this custom filter must be the first in the list of all applied filters (orderBy, etc.), and it will add an additional index property (the name is customizable) to each Collection object.

+18
Apr 10 '14 at 3:33
source share

I started to study angular and ran into a similar problem, and based on @ pkozlowski-opensource answer, I solved it just with something like

 <a> <img src="img/delete.png" ng-click="removeItem(items.indexOf(item))"> {{items.indexOf(item)}} </a> 
+14
Sep 16 '14 at 5:59
source share

Try the following:

 $scope.remove = function(subtask) { var idx = $scope.subtasks.indexOf(subtask), st = $scope.currentTask.subtasks[idx]; // remove from DB SubTask.remove({'subtaskId': subtask.id}); // remove from local array $scope.subtasks.splice(idx,1); } 

On my blog, you can find a detailed explanation in this entry .

+3
Jul 25 '13 at 12:49 on
source share

I would just leave a comment, but I do not have a "reputation".

Decision

mile is what I need too. To answer the question of pkozlowski.opensource: when you have either ngRepeat s nested, a dynamic list (for example, when you enable deletion), or both (this is my case), using $index does not work, because it will not be the right index for the source data after sorting and using ngInit to cache the value does not work either because it is not overestimated when the list changes.

Note that the mile solution allows you to customize the property name of the attached index by passing the parameter <tr ng-repeat="item in items | index:'originalPosition' | orderBy:'Store.storeName'">

My modified version:

 .filter( 'repeatIndex', function repeatIndex() { // This filter must be called AFTER 'filter'ing // and BEFORE 'orderBy' to be useful. return( function( array, index_name ) { index_name = index_name || 'index'; array.forEach( function( each, i ) {each[ index_name ] = i;}); return( array ); }); }) 
+1
Aug 6 '14 at 18:45
source share

If someone needs to use $index , you can specify the name in a sorted / filtered array:

 <tr ng-repeat="item in sortedItems = (items | orderBy:'Store.storeName') track by $index"> 

See my answer here .

-2
Jul 24 '17 at 10:40
source share



All Articles