可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am new to Angular.js and have some problems sorting my array and working on that sorted data.
I have a list with items and want so sort it by "Store.storeName", which is working so far. But after sorting the data, my delete-function is not working anymore. I think thats because the $index is wrong after sorting, and so the wrong data is deleted.
How can I solve that? Ordering the data in the scope and not in the view? How to do that?
Here is some relevant code:
In the 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 the specific data:
$scope.removeItem = function(index){
$scope.items.splice(index,1);
}
This works nicely before ordering in the View.
If something important is missing, please let me now.
Thanks!
回答1:
Instead or relaying on the $index
- which - as you have noticed - will point to the index in a sorted / filtered array, you can pass the item itself to your removeItem
function:
<a><img src="img/delete.png" ng-click="removeItem(item)">{{$index}}</a>
and modify the removeItem
function to find an index using the indexOf
method of an array as follows:
$scope.removeItem = function(item){
$scope.items.splice($scope.items.indexOf(item),1);
}
回答2:
I had the same problem and other answers in this topic are not suitable for my situation.
I've solved my problem with 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 this way:
<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 the collections of objects.
Please, take into account that this custom filter should be the first one in the list of all filters applied (orderBy etc.) and it will add the additional property index
(the name is customizable) into the each object of the collection.
回答3:
I started to learn angular and faced similar trouble, and based on the answer of @pkozlowski-opensource, I solved it just with something like
<a>
<img src="img/delete.png" ng-click="removeItem(items.indexOf(item))">
{{items.indexOf(item)}}
</a>
回答4:
Try this:
$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);
}
You can find verbose explanation in this entry in my blog.
回答5:
I would've just left a comment, but I don't have the "reputation".
mile's solution is exactly what I needed too. To answer pkozlowski.opensource's question: when you have either nested ngRepeat
s, a dynamic list (e.g. where you allow removals), or both (which is my case), using $index
does not work because it will be the wrong index for the back-end data after sorting and using ngInit
to cache the value does not work either because it's not re-evaluated when the list changes.
Note that mile's solution allows for the attached index property name to be customized by passing a parameter <tr ng-repeat="item in items | index:'originalPosition' | orderBy:'Store.storeName'">
My tweaked 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 );
});
})
回答6:
In case someone needs to use $index
, you can give a name to the sorted / filtered array :
<tr ng-repeat="item in sortedItems = (items | orderBy:'Store.storeName') track by $index">
See my answer here.