Using $index
works perfectly well in basic cases, and @charlietfl's answer is great. But sometimes, $index
isn't enough.
Imagine you have a single array, which you're presenting in two different ng-repeat's. One of those ng-repeat's is filtered for objects that have a truthy property, and the other is filtered for a falsy property. Two different filtered arrays are being presented, which derive from a single original array. (Or, if it helps to visualize: perhaps you have a single array of people, and you want one ng-repeat for the women in that array, and another for the men in that same array.) Your goal: delete reliably from the original array, using information from the members of the filtered arrays.
In each of those filtered arrays, $index won't be the index of the item within the original array. It'll be the index in the filtered sub-array. So, you won't be able to tell the person's index in the original people
array, you'll only know the $index from the women
or men
sub-array. Try to delete using that, and you'll have items disappearing from everywhere except where you wanted. What to do?
If you're lucky enough be using a data model includes a unique identifier for each object, then use that instead of $index, to find the object and splice
it out of the main array. (Use my example below, but with that unique identifier.) But if you're not so lucky?
Angular actually augments each item in an ng-repeated array (in the main, original array) with a unique property called $$hashKey
. You can search the original array for a match on the $$hashKey
of the item you want to delete, and get rid of it that way.
Note that $$hashKey
is an implementation detail, not included in the published API for ng-repeat. They could remove support for that property at any time. But probably not. :-)
$scope.deleteFilteredItem = function(hashKey, sourceArray){
angular.forEach(sourceArray, function(obj, index){
// sourceArray is a reference to the original array passed to ng-repeat,
// rather than the filtered version.
// 1. compare the target object's hashKey to the current member of the iterable:
if (obj.$$hashKey === hashKey) {
// remove the matching item from the array
sourceArray.splice(index, 1);
// and exit the loop right away
return;
};
});
}
Invoke with:
ng-click="deleteFilteredItem(item.$$hashKey, refToSourceArray)"
EDIT: Using a function like this, which keys on the $$hashKey
instead of a model-specific property name, also has the significant added advantage of making this function reusable across different models and contexts. Provide it with your array reference, and your item reference, and it should just work.