Many have questioned how to implement item removal within the ngRepeat directive. Through my research, I discovered that it involves using ngClick to trigger a removal function with the item's $index.
However, I haven't been able to find an example that addresses multiple ngRepeats:
<div ng-controller="MyController">
<div ng-repeat="email in user.emails">
{{ email }} <a href>Remove</a>
</div>
<div ng-repeat="phone in user.phones">
{{ phone }} <a href>Remove</a>
</div>
</div>
To handle this scenario, I would need to create $scope.removePhone and $scope.removeEmail functions that are called using ngClick on the Remove anchor. However, I am seeking a more universal solution, especially since I have numerous pages with multiple ngRepeats.
I am considering writing a directive that can be placed on the Remove anchor and perform the following actions:
- Locate the nearest ngRepeat element among parent elements.
- Determine the collection being iterated over ('user.emails' or 'user.phones').
- Remove the element at the $index from that model.
This is how the updated markup might look:
<div ng-controller="MyController">
<div ng-repeat="email in user.emails">
{{ email }} <a href remove-directive="$index">Remove</a>
</div>
<div ng-repeat="phone in user.phones">
{{ phone }} <a href remove-directive="$index">Remove</a>
</div>
</div>
Is it possible to achieve what I'm looking for, and what approach should I take?
Current workaround
Presently, I am using a makeshift solution to address this issue. While it may not be ideal, it serves its purpose until I discover a better method.
myAppModule.controller('MyController', function ($scope, $parse, $routeParams, User) {
$scope.user = User.get({id: $routeParams.id});
$scope.remove = function ($index, $event) {
// TODO: Find a way to make a directive that does this. This is ugly. And probably very wrong.
var repeatExpr = $($event.currentTarget).closest('[ng-repeat]').attr('ng-repeat');
var modelPath = $parse(repeatExpr.split('in')[1].replace(/^\s+|\s+$/g, ''));
$scope.$eval(modelPath).splice($index, 1);
};
});
In the DOM:
<div ng-repeat="email in user.email" class="control-group">
<label class="control-label">
{{ "Email Address"|_trans }}
</label>
<div class="controls">
<input type="text" ng-model="email.address">
<span class="help-inline"><a href ng-click="remove($index, $event)">{{ "Delete"|_trans }}</a></span>
</div>
</div>