0

I have an array of items bound to <li> elements in a <ul> with AngularJS. I want to be able to click "remove item" next to each of them and have the item removed.

This answer on StackOverflow allows us to do exactly that, but because the name of the array which the elements are being deleted from is hardcoded it is not usable across lists.

You can see an example here on JSfiddle set up, if you try clicking "remove" next to a Game, then the student is removed, not the game.

Passing this back from the button gives me access to the Angular $scope at that point, but I don't know how to cleanly remove that item from the parent array.

I could have the button defined with ng-click="remove('games',this)" and have the function look like this:

$scope.remove = function (arrayName, scope) {
  scope.$parent[arrayName].splice(scope.$index,1);
}

(Like this JSFiddle) but naming the parent array while I'm inside it seems like a very good way to break functionality when I edit my code in a year.

Any ideas?

Community
  • 1
  • 1
JP.
  • 5,507
  • 15
  • 59
  • 100
  • Why don't you use two functions? One to remove students and another one to remove games. – Wagner Francisco Apr 25 '13 at 11:15
  • This is a simplification of the system I'm actually building - I have ~20 different lists on the page, and it seems massively against DRY to write a function for each! – JP. Apr 25 '13 at 11:22

1 Answers1

2

I did not get why you were trying to pass this .. You almost never need to deal with this in angular. ( And I think that is one of its strengths! ).

Here is a fiddle that solves the problem in a slightly different way.

http://jsfiddle.net/WJ226/5/

The controller is now simplified to

function VariousThingsCtrl($scope) {

    $scope.students = students;
    $scope.games = games;

    $scope.remove = function (arrayName,$index) {
      $scope[arrayName].splice($index,1);
    }
}

Instead of passing the whole scope, why not just pass the $index ? Since you are already in the scope where the arrays are located, it should be pretty easy from then.

ganaraj
  • 26,841
  • 6
  • 63
  • 59
  • Ah! Certainly a good alternative - however if I decide to rename the scope variable later in development (eg. `$scope.outdoorGames = games;`) I now need to remember to go and change the first argument of remove in the html partial, which feels wrong to me! (I also can't use this with arrays held deep within a $scope object - though it wouldn't be too tricky, it gets more complex) – JP. Apr 25 '13 at 14:01
  • Even if you do $scope.outdoorGames = games; It will still work because outdoorGames and games will be referring to the same object. I dont think there is a solution that is array identity agnostic.. – ganaraj Apr 25 '13 at 14:08
  • I think you might be right - I've been toying with changing the DOM using the `$event` object instead (hoping that the 2-way binding would remove the array item) but sadly it doesn't! http://jsfiddle.net/jphastings/WJ226/7/ – JP. Apr 25 '13 at 14:20
  • I've ended up referencing the array I want to remove items from in the `ng-click` - http://jsfiddle.net/jphastings/SeEhK/1/ - this feels pretty dirty as I've put the repeated elements in an included template, so I can add new items too, which means I'm referring to the array by name in two places - dangerous for code changes! Thanks for your help though :) – JP. Apr 25 '13 at 14:42